C# 子線程與主線程之間的通信
先說明一下,本人最近遇到了什麽問題,就是在寫寫消息隊列的時候,發現消息隊列每次接收一個消息的時候都是創建了一個新的線程。這樣就導致了消息處理的時候沒有在主線程上進行,然而其中的一些步事項是要通過主線程才能操作的。這樣就引出了一個子線程怎麽去通知主線程要做哪些事情呢?
為了解決上面的問題我找了好的多資料,好多都是用委托,去解決了,然後我又看了我的項目通過這種beginInvoker的這種辦法解決不是很好用。並不能解決的當前的問題,在這個時候我發現了SynchronizationContext對象。這個對像的用處就是可以記錄一個線程的上下文然後再子線程處理完之後,要用到主要程去操作的時候可以去Post或者Send一個事件支解決,這樣就很方便,代碼如下:
class TestClient { private Thread workThread; private SynchronizationContext mainThreadSynContext; public TestClient()//構造函數當然是主線程執行的 { mainThreadSynContext = SynchronizationContext.Current; //在這裏記錄主線程的上下文 workThread = new Thread(newView CodeThreadStart(DoWork));//創建一個新的線程 } private void OnConnected(object state)//由於是主線程的同步對象Post調用,這個是在主線程中執行的 { //這裏就回到了主線程裏面了 //做一些事情 } private void DoWork()//這個是workThread線程執行的 { //這兒做些事(連接什麽的。。。) //這而幹完了 mainThreadSynContext.Post(new SendOrPostCallback(OnConnected), null);//通知主線程 } }
註意:SynchronizationContext的對象不是所有線程都被附加的,只有UI主線程會被附加。對於UI線程來說,是如何將SynchronizationContext這個對象附加到線程上的呢?
在Form1 form = new Form1()之前,SynchronizationContext對象是為空,而當實例化Form1窗體後,SynchronizationContext對象就被附加到這個線程上了。所以可以得出答案了:當Control對象被創建的同時,SynchronizationContext對象也會被創建並附加到線程上。所有在使用時,一定要等窗體InitializeComponent(); 這個完成後 它才能得到一個不這NULL的對象。
最後SynchronizationContext的Sendt()和Post()二個方法的區別:
Send() 是簡單的在當前線程上去調用委托來實現(同步調用)。也就是在子線程上直接調用UI線程執行,等UI線程執行完成後子線程才繼續執行。
Post() 是在線程池上去調用委托來實現(異步調用)。這是子線程會從線程池中找一個線程去調UI線程,子線程不等待UI線程的完成而直接執行自己下面的代碼。
C# 子線程與主線程之間的通信