2012-08-25 44 views
4

由於ProgressChanged事件處理程序是從DoWork事件處理程序中的某個位置引發的,因此不應該在異步操作線程上調用它,該線程也運行在其上,而不是UI線程,因此需要Invoke或BeginInvoke來操作控件?爲什麼BackgroundWorker不需要在ProgressChanged事件處理程序中調用?

我的猜測是ReportProgress方法中發生了一些魔法,但它怎麼知道哪一個是調用ProgressChanged事件處理程序的正確線程?

+1

http://msdn.microsoft.com/en-us/library/system.windows.forms.windowsformssynchronizationcontext或者您可以使用ilspy查看下面的內容 – rene

回答

6

當你調用RunWorkerAsync,在BackgroundWorker內部創建與當前同步上下文相關聯的新AsyncOperation下,由AsyncOperationManager.SynchronizationContext靜態屬性檢索。

此同步上下文將是派生自SynchronizationContext的類的實例。具體類型取決於您的應用程序使用的同步模型提供程序。如果您正在運行Windows窗體,它將是WindowsFormsSynchronizationContext;在WPF上;這將是DispatcherSynchronizationContext

當您隨後致電ReportProgress在後臺線程,則BackgroundWorker將內部調用Post在上述SynchronizationContext實例,從而分派操作相關線程異步。

在Windows窗體中,這實現爲Control.BeginInvoke調用;在WPF上,它變成了一個Dispatcher.BeginInvoke調用。

+0

我剛剛讀了一些關於'WindowsFormsSynchronizationContext'的內容,如上所述雷內的評論。只是讓我明白了:'AsyncOperationManager.SynchronizationContext'產生的是'''WindowsFormsSynchronizationContext',它默認'AutoInstall'設置爲'true',因此知道..究竟是什麼?消息隊列正在運行的線程,還是創建第一個控件的線程?還是隻是保存「主窗體」,以便稍後調用'BeginInvoke'?作爲一個方面說明,我注意到當操作控件在另一個線程上創建時,它不起作用。 – dialer

+0

'WindowsFormsSynchronizationContext'存儲一個內部引用,用於調用'BeginInvoke''' Control'(通常是'Form')。 – Douglas

相關問題