可以參考”C# 對 Windows 窗體控件進行線程安全調用“一文來看。
在做網絡連接程序的時候碰到一個問題:每當連接到來時,都創建一個新的接收線程,而該接收線程在接收到消息時,可以創建一個新的對話窗口,而該窗口不能阻塞該接收線程的下一輪消息的接收,而且該接收線程還要把接收到的消息顯示在該窗口上
Form.ShowDialog();方法彈出模態對話框,而模態對話框會阻塞后面代碼的執行,導致接收線程無法繼續執行(除非該模態窗口被關閉)
剛開始想到的解決辦法,就是:通過Form.Show();方法,顯示非模態的窗口
非模態對話框有幾個問題:
(1) 生命期限問題:由於是在線程的一輪執行中創建的,所以,該對象可能在該輪結束后被垃圾回收機制自動清除掉;
(2) 模態對話框沒有系統消息機制,需要自己寫;(好像是這樣的,沒用過...)
(3) 在代碼中嘗試了一下,沒有創建消息機制,只是顯示窗口。但該窗口處於假死狀態,根本沒法用。
由於上述的幾個困難,只能另覓它途了...
成功實驗-----異步委托
在看其他文章的時候,偶然看到Control.Invoker()方法,該方法可執行自定義或系統定義的委托。
突然想起來,委托可以通過用Invoke()方法同步執行(阻塞執行),而通過BeginInvoke()方法異步執行,如果是異步執行的話,應該是不會阻塞線程的執行吧...
於是,做了如下的例子:
注意事項:
通過Invoke()/BeginInvoke()調用委托,必須由已經出現的控件來調用,否則會出現錯誤提示:“未經處理的異常: System.InvalidOperationException: 在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。”
1) 打開窗口代碼:
- void openNewForm()
- {
- Form2 newForm = new Form2();
- newForm.ShowDialog();
- }
(2) 線程入口函數
- //線程入口函數
- void _threadProc()
- {
- //定義一個委托實例,該實例執行打開窗口代碼
- MethodInvoker mi = new MethodInvoker(openNewForm);
- BeginInvoke(mi);
- //如果沒有阻塞的話,該段代碼應該可執行
- Console.WriteLine("新打開的窗口沒有阻塞之后的執行");
- Console.ReadLine();
- }
(3) 創建,並執行線程
- Thread newThread = new Thread(new ThreadStart(_threadProc));
- newThread.Start();
4) 設置項目的輸出類型為:控制台應用程序(這樣執行的時候會同時彈出控制台和窗口)
執行結果如下:
可見,新打開的模式窗口並沒有阻塞線程的執行!
因為,如果是同步調用的話,在Form2窗口關閉之前,“新打開的窗口沒有阻塞之后的執行”就不會有輸出。
本文非自創,可查看原文:http://blog.csdn.net/xiaobai1593/article/details/7290421