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