2012-05-03 95 views
0

我有包含像這樣的[STAThread]主:跨線程問題,BackgroundWorker的和ReportProgress

try 
{ 
    // Start the port enumerator. 

    Enumerator enumerator = new Enumerator(); 

    // Display the main window and start everything going. 

    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(new TopViewForm(ref enumerator)); 
} 
catch (Exception) 
{ 
} 

枚舉對象本身包含一個後臺工作線程。後臺工作被初始化這樣的:現在

MyBackgroundWorker = new BackgroundWorker(); 
MyBackgroundWorker.WorkerSupportsCancellation = true; 
MyBackgroundWorker.WorkerReportsProgress = true; 
MyBackgroundWorker.DoWork +=new DoWorkEventHandler(MyBackgroundWorker_DoWork); 
MyBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(MyBackgroundWorker_ProgressChanged); 
MyBackgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(MyBackgroundWorker_RunWorkerCompleted); 
MyBackgroundWorker.RunWorkerAsync(); 

,以報告進展情況回主窗體(TopViewForm的情況下),在枚舉線程調用一些適當的用戶對象ReportProgress。我假設ReportProgress將以ProgressChanged事件的形式到達,並在主UI線程上執行,這是Enumerator本身創建的線程(即不是BackgroundWorker的線程)。

鑑於這種情況,當我嘗試在主進程線程的TreeView中設置節點以響應來自此對象的事件時,出現跨線程違例錯誤,該怎麼辦? ProgressChanged明確不是似乎是在主進程線程上運行,看着調用堆棧。

我假設然後,Application.Run生成一個新的線程並運行該表單?但文件中另有說明。要麼我犯了一個愚蠢的錯誤,要麼我在這裏不明白。

有沒有人有任何想法?

+0

一個Bgw與Application.Run()緊密合作,因此將它移動到表單中。 –

+0

好想你們倆。如果我在表單中移動它,它可以正常工作。 – Robinson

+0

那麼,第一個添加它作爲答案得到的點:) – Robinson

回答

2

BackgroundWorker依賴於當前正在設置的SynchronizationContext的功能。 ProgressChanged事件實現爲SendOrPostCallback Delegate,並且如msdn文檔中所述,SendOrPostCallback表示要將消息分派到同步上下文時要執行的回調方法。將表單設計器中的BackgroundWorker添加到表單可以正確設置SynchronizationContext。在你的情況BackgroundWorker沒有分配SynchronizationContext。

+0

啊,這是實際的正確答案。感謝您的信息。 – Robinson

3

我相信在第一次調用Application.Run之前,進度更改事件正在運行。如果您不從Main啓動後臺工作人員,而是從其中一個表單中啓動後臺工作人員,則確保在創建後臺工作人員時已經存在消息循環並開始報告進度。