Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
    }

Looking at reflector, the Control.BeginInvoke() appears to use:

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

Which seems to eventually call some native functions like PostMessage(), couldn't exactly figure out the flow from reflector (pesky compiler goto optimizations)

Whereas BackgroundWorker.Invoke() appears to use:

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

Which seems to eventually call ThreadPool.QueueUserWorkItem()

(I'm just guessing these are the relevant function calls for each case.) If I understand correctly, using the ThreadPool would not guarantee execution order whereas using the Post mechanism would. Perhaps that would be a potential difference ? (EDIT - I couldn't synthesize such a situation - call order seems to be preserved in both cases, at least in my simple tests.)

Thanks!

like image 712
Ohad Schneider Avatar asked May 16 '26 16:05

Ohad Schneider


1 Answers

They are both the same. The call you're seeing in BackgroundWorker uses SynchronizationContext. Indeed the default implementation of the Post() method uses the thread pool, but when starting a Windows Forms app, the default synchronization context is replaced by WindowsFormsSynchronizationContext, which actually calls Control.BeginInvoke().

like image 80
Eli Arbel Avatar answered May 18 '26 20:05

Eli Arbel