由于ProgressChanged
事件处理程序是从事件处理程序中的某个地方引发的DoWork
,难道不应该在异步操作线程上调用它们DoWork
,而不是在 UI 线程上运行,因此需要调用或BeginInvoke
操作控件?
我的猜测是该ReportProgress
方法中正在发生一些魔术,但它怎么知道,哪个是调用ProgressChanged
事件处理程序的正确线程?
由于ProgressChanged
事件处理程序是从事件处理程序中的某个地方引发的DoWork
,难道不应该在异步操作线程上调用它们DoWork
,而不是在 UI 线程上运行,因此需要调用或BeginInvoke
操作控件?
我的猜测是该ReportProgress
方法中正在发生一些魔术,但它怎么知道,哪个是调用ProgressChanged
事件处理程序的正确线程?
当您调用RunWorkerAsync
时,BackgroundWorker
内部会创建一个AsyncOperation
与当前同步上下文关联的新上下文,如通过AsyncOperationManager.SynchronizationContext
静态属性检索的那样。
此同步上下文将是派生自 的类的实例SynchronizationContext
。具体类型取决于您的应用程序使用的同步模型提供程序。如果您正在运行 Windows 窗体,它会是WindowsFormsSynchronizationContext
;在 WPF 上;会的DispatcherSynchronizationContext
。
当您随后调用ReportProgress
后台线程时,BackgroundWorker
将在内部调用Post
上述SynchronizationContext
实例,从而将操作异步分派到关联线程。
在 Windows 窗体中,这是作为Control.BeginInvoke
调用实现的;在 WPF 上,它变成了一个Dispatcher.BeginInvoke
调用。