为什么BackgroundWorker不需要在ProgressChanged事件处理程序中调用?

由于ProgressChanged事件处理程序是从DoWork事件处理程序中的某个位置引发的,因此它们不应该在异步操作线程上调用, DoWork也运行,而不是UI线程,因此需要Invoke或BeginInvoke来操作控件?

我的猜测是在ReportProgress方法中发生了一些魔法,但它怎么知道,哪一个是调用ProgressChanged事件处理程序的正确线程?

当您调用RunWorkerAsyncBackgroundWorker会在内部创建与当前同步上下文关联的新AsyncOperation ,这是通过AsyncOperationManager.SynchronizationContext静态属性检索的。

此同步上下文将是从SynchronizationContext派生的类的实例。 特定类型取决于应用程序使用的同步模型提供程序。 如果您正在运行Windows窗体,那么它将是WindowsFormsSynchronizationContext ; 在WPF上; 它将是DispatcherSynchronizationContext

当您随后在后台线程上调用ReportProgress时, BackgroundWorker将在上面的SynchronizationContext实例内部调用Post ,从而异步地将操作分派给关联的线程。

在Windows窗体中,这是作为Control.BeginInvoke调用实现的; 在WPF上,它成为Dispatcher.BeginInvoke调用。