Diffrernce between BackgroundWorker.ReportProgress () and Control.BeginInvoke ()

What is the difference between options 1 and 2 in the following?

    private void BGW_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i=1; i<=100; i++)
        {
            string txt = i.ToString();
            if (Test_Check.Checked)
                //OPTION 1
                Test_BackgroundWorker.ReportProgress(i, txt); 
            else
                //OPTION 2
                this.BeginInvoke((Action<int, string>)UpdateGUI, 
                                  new object[] {i, txt});
        }
    }

    private void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        UpdateGUI(e.ProgressPercentage, (string)e.UserState);
    }

    private void UpdateGUI(int percent, string txt)
    {
        Test_ProgressBar.Value = percent;
        Test_RichTextBox.AppendText(txt + Environment.NewLine);
    }

When looking at the reflector, Control.BeginInvoke () will use:

this.FindMarshalingControl().MarshaledInvoke(this, method, args, 1);

Which seems to end up calling some native functions like PostMessage (), couldn’t pinpoint the stream from the reflector (optimizing the compiler optimizer)

While BackgroundWorker.Invoke () seems to use:

this.asyncOperation.Post(this.progressReporter, args);

Which seems to end up calling ThreadPool.QueueUserWorkItem ()

( , .) , ThreadPool , Post . , ? ( - ​​ - , , , , .)

!

+3
3

. , BackgroundWorker, SynchronizationContext. , Post() , Windows Forms WindowsFormsSynchronizationContext, Control.BeginInvoke().

+2

, Control.Invoke , UpdateGUI , BackgroundWorker.ReportProgress ( , BackgroundWorker ).

, , Control.BeginInvoke ( ).

+2

I found a significant difference. Closing the form while BGW is running will cause this.Invoke () and this.BeginInvoke () to throw an ObjectDisposedException. The BGW ReportProgress engine circumvents this. To enjoy the best of both worlds, the following drawing works beautifully

public partial class MyForm : Form
{
    private void InvokeViaBgw(Action action)
    {
        Packing_Worker.ReportProgress(0, action);
    }

    private void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (this.IsDisposed) return; //You are on the UI thread now, so no race condition

        var action = (Action)e.UserState;
        action();
    }

    private private void BGW_DoWork(object sender, DoWorkEventArgs e)
    {
       //Sample usage:
       this.InvokeViaBgw(() => MyTextBox.Text = "Foo");
    }
}
0
source

Source: https://habr.com/ru/post/1746188/


All Articles