訪問 Windows 窗體控件本質上不是線程安全的。如果有兩個或多個線程操作某一控件的狀態,則可能會迫使該控件進入一種不一致的狀態。還可能出現其他與線程相關的 bug,包括爭用情況和死鎖。確保以線程安全方式訪問控件非常重要。
.NET Framework 有助于在以非線程安全方式訪問控件時檢測到這一問題。在調試器中運行應用程序時,如果創建某控件的線程之外的其他線程試圖調用該控件,則調試器會引發一個 InvalidOperationException,并提示消息:“從不是創建控件 control name 的線程訪問它。”
有三種方法可以從線程訪問Win窗體的控件:非線程安全方式;線程安全調用;使用BackgroundWorker進行的線程安全調用。其中,只有線程的安全調用可以宏觀并行處理。(另外兩種方式都是在線程運行時接受命令,但在線程執行完以后才執行)。
一:對Windows窗體控件的非線程安全調用
該方式是從輔助線程直接調用。調用應用程序時,調試器會引發一個InvalidOperationException,警告對控件的調用不是線程安全的。
可以通過將 CheckForIllegalCrossThreadCalls 屬性的值設置為 false 來禁用此異常。這會使控件以與在 Visual Studio 2003 下相同的方式運行。
具體做法如下:





二:對Windows窗體控件的線程安全調用
對窗體控件的線程安全調用需要用委托的方式。
主要思路:
1、查詢控件的 InvokeRequired 屬性。
2、如果 InvokeRequired 返回 true,則使用實際調用控件的委托來調用 Invoke。
3、如果 InvokeRequired 返回 false,則直接調用控件。
例子:在TextBox控件中輸出相應的信息,SetText為textbox的內容設置方法,SetTextDelegate的委托類型封裝 SetText方法。TextBox控件的InvokeRequired返回true是,SetText方法創建SetTextDelegate的一個實 例,并調用窗體的Invoke方法。是的SetText方法被創建TextBox控件的線程調用。













































三、使用 BackgroundWorker 進行的線程安全調用
在應用程序中實現多線程的首選方式是 使用 BackgroundWorker 組件。BackgroundWorker 組件使用事件驅動模型實現多線程。輔助線程運行 DoWork 事件處理程序,創建控件的線程運行 ProgressChanged 和 RunWorkerCompleted 事件處理程序。注意不要從 DoWork 事件處理程序調用您的任何控件。
下面的代碼示例不異步執行任何工作,因此沒有 DoWork 事件處理程序的實現。TextBox 控件的 Text 屬性在 RunWorkerCompleted 事件處理程序中直接設置。












