Search code examples
c#.netbackgroundworker

Why doesn't a BackgroundWorker need Invoke in the ProgressChanged event handler?


Since the ProgressChanged event handler is raised from somewhere within the DoWork event handlers, shouldn't they be called on the asynchronous operation thread, which DoWork also runs on, instead of the UI thread, and therefore require Invoke or BeginInvoke to manipulate controls?

My guess is that some magic is happening within the ReportProgress method, but how does it even know, which one is the correct thread to invoke the ProgressChanged event handlers on?


Solution

  • When you call RunWorkerAsync, the BackgroundWorker internally creates a new AsyncOperation associated with the current synchronization context, as retrieved through the AsyncOperationManager.SynchronizationContext static property.

    This synchronization context would be an instance of a class deriving from SynchronizationContext. The specific type depends on the synchronization model provider your application uses. If you’re running Windows Forms, it would be WindowsFormsSynchronizationContext; on WPF; it would be DispatcherSynchronizationContext.

    When you subsequently call ReportProgress on the background thread, the BackgroundWorker would internally call Post on the aforementioned SynchronizationContext instance, thereby dispatching the operation to the associated thread asynchronously.

    In Windows Forms, this is implemented as a Control.BeginInvoke call; on WPF, it becomes a Dispatcher.BeginInvoke call.