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

.net, backgroundworker, c#

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.

Problem

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?

Original source