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