由於ProgressChanged
事件處理程序是從DoWork
事件處理程序中的某個位置引發的,因此不應該在異步操作線程上調用它,該線程也運行在其上,而不是UI線程,因此需要Invoke或BeginInvoke
來操作控件?爲什麼BackgroundWorker不需要在ProgressChanged事件處理程序中調用?
我的猜測是ReportProgress
方法中發生了一些魔法,但它怎麼知道哪一個是調用ProgressChanged
事件處理程序的正確線程?
由於ProgressChanged
事件處理程序是從DoWork
事件處理程序中的某個位置引發的,因此不應該在異步操作線程上調用它,該線程也運行在其上,而不是UI線程,因此需要Invoke或BeginInvoke
來操作控件?爲什麼BackgroundWorker不需要在ProgressChanged事件處理程序中調用?
我的猜測是ReportProgress
方法中發生了一些魔法,但它怎麼知道哪一個是調用ProgressChanged
事件處理程序的正確線程?
當你調用RunWorkerAsync
,在BackgroundWorker
內部創建與當前同步上下文相關聯的新AsyncOperation
下,由AsyncOperationManager.SynchronizationContext
靜態屬性檢索。
此同步上下文將是派生自SynchronizationContext
的類的實例。具體類型取決於您的應用程序使用的同步模型提供程序。如果您正在運行Windows窗體,它將是WindowsFormsSynchronizationContext
;在WPF上;這將是DispatcherSynchronizationContext
。
當您隨後致電ReportProgress
在後臺線程,則BackgroundWorker
將內部調用Post
在上述SynchronizationContext
實例,從而分派操作相關線程異步。
在Windows窗體中,這實現爲Control.BeginInvoke
調用;在WPF上,它變成了一個Dispatcher.BeginInvoke
調用。
我剛剛讀了一些關於'WindowsFormsSynchronizationContext'的內容,如上所述雷內的評論。只是讓我明白了:'AsyncOperationManager.SynchronizationContext'產生的是'''WindowsFormsSynchronizationContext',它默認'AutoInstall'設置爲'true',因此知道..究竟是什麼?消息隊列正在運行的線程,還是創建第一個控件的線程?還是隻是保存「主窗體」,以便稍後調用'BeginInvoke'?作爲一個方面說明,我注意到當操作控件在另一個線程上創建時,它不起作用。 – dialer
'WindowsFormsSynchronizationContext'存儲一個內部引用,用於調用'BeginInvoke''' Control'(通常是'Form')。 – Douglas
http://msdn.microsoft.com/en-us/library/system.windows.forms.windowsformssynchronizationcontext或者您可以使用ilspy查看下面的內容 – rene