C#SynchronizationContext以及Send和Post使用解讀
c#synchronizationcontext以及send和post使用解讀
c# synchronizationcontext及send和post使用
1、(synchronizationcontext)同步上下文的作用
synchronizationcontext其實就是實現線程之間通訊的。
2、創建(synchronizationcontext)同步上下文的方法
- 1)直接new創建一個synchronizationcontext同步上下文對象。
- 2)winform程序通過synchronizationcontext.current獲取ui線程的同步上下文對象。
- 3)asyncoperation和asyncoperationmanager類來操作同步上下文對象,不直接訪問同步上下文對象(synchronizationcontext),推薦這程方法。
3、(synchronizationcontext)同步上下文的send和post方法
看了一些解釋send和post方法,感覺弄得很復雜,我感覺其實簡單來說,
- 1)send方法就是同步調用,在當前線程上調用委托。
- 2)post方法就是異步調用,在線程池中的線程調用委托。
4、示例代碼
1)(synchronizationcontext)同步上下文使用示例代碼
using system; using system.threading; namespace synchronizationcontextexample { ? ? public class mysynchronizedclass ? ? { ? ? ? ? private thread workerthread; ? ? ? ? private synchronizationcontext context; ? ? ? ? public event eventhandler somethinghappened; ? ? ? ? public mysynchronizedclass() ? ? ? ? { ? ? ? ? ?//獲取當前synchronizationcontext非常重要對象在構造函數中。我們想要的 ? ? ? ? ?//屬于線程的synchronizationcontext對象 ? ? ? ? ?//這個對象正在被創建。 ? ? ? ? ?//context= synchronizationcontext.current;當前線程可能沒有synchronizationcontext對象;該線程尚未為設置synchronizationcontext對象。 ? ? ? ? ?//如果是這樣,我們可以通過創建synchronizationcontext來簡化 ? ? ? ? ? ? if(context == null) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? context = new synchronizationcontext(); ? ? ? ? ? ? } ? ? ? ? ? ? workerthread = new thread(new threadstart(dowork)); ? ? ? ? ? ? workerthread.start(); ? ? ? ? } ? ? ? ? private void dowork() ? ? ? ? { ? ? ? ? ? ? context.post(new sendorpostcallback(delegate(object state) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? eventhandler handler = somethinghappened; ? ? ? ? ? ? ? ? if(handler != null) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? handler(this, eventargs.empty); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }), null); ? ? ? ? } ? ? } }
2)使用asyncoperation和asyncoperationmanager類示例代碼
using system; using system.threading; using system.componentmodel; namespace synchronizationcontextexample { ? ? public class mysynchronizedclass ? ? { ? ? ? ? private thread workerthread; ? ? ? ? private asyncoperation operation; ? ? ? ? public event eventhandler somethinghappened; ? ? ? ? public mysynchronizedclass() ? ? ? ? { ? ? ? ? ? ? operation = asyncoperationmanager.createoperation(null); ? ? ? ? ? ? workerthread = new thread(new threadstart(dowork)); ? ? ? ? ? ? workerthread.start(); ? ? ? ? } ? ? ? ? private void dowork() ? ? ? ? { ? ? ? ? ? ? operation.post(new sendorpostcallback(delegate(object state) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? eventhandler handler = somethinghappened; ? ? ? ? ? ? ? ? if(handler != null) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? handler(this, eventargs.empty); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }), null); ? ? ? ? ? ? operation.operationcompleted(); ? ? ? ? } ? ? } }
c#同步上下文synchronizationcontext學習筆記
提供在各種同步模型中傳播同步上下文的基本功能。同步上下文的工作就是確保調用在正確的線程上執行。
同步上下文的基本操作
current 獲取當前同步上下文
var context = synchronizationcontext.current;
send 一個同步消息調度到一個同步上下文。
sendorpostcallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//todo: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}; context.send(callback,null);
- send調用后會阻塞直到調用完成。
- post 將異步消息調度到一個同步上下文。
sendorpostcallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //todo: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }; context.post(callback,null);
和send的調用方法一樣,不過post會啟動一個線程來調用,不會阻塞當前線程。
使用同步上下文來更新ui內容
無論winfroms和wpf都只能用ui線程來更新界面的內容
常用的調用ui更新方法是inovke(winfroms):
private void button_click(object sender, eventargs e) { ? ? ? ?threadpool.queueuserworkitem(backgroudrun); } private void backgroudrun2(object state) { ? ? ? ? ? ? this.invoke(new action(() => ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? label1.text = "hello invoke"; ? ? ? ? ? ? ? ? ? ? ? ?})); }
使用同步上下文也可以實現相同的效果,winfroms和wpf繼承了synchronizationcontext,使同步上下文能夠在ui線程或者dispatcher線程上正確執行
system.windows.forms. windowsformssynchronizationcontext system.windows.threading. dispatchersynchronizationcontext
調用方法如下:
private void button_click(object sender, eventargs e) { ? ? ? ? ? ?var context = synchronizationcontext.current; //獲取同步上下文 ? ? ? ? ? ?debug.assert(context != null); ? ? ? ? ? ?threadpool.queueuserworkitem(backgroudrun, context);? } private void backgroudrun(object state) { ? ? var context = state as synchronizationcontext; //傳入的同步上下文 ? ? debug.assert(context != null); ? ? sendorpostcallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label1.text = "hello synchronizationcontext"; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }; ? ? context.send(callback,null); //調用 }
使用.net4.0的task 可以簡化成
private void button_click(object sender, eventargs e) { ? ? ? ? ? ? var ?scheduler = taskscheduler.fromcurrentsynchronizationcontext(); // 創建一個synchronizationcontext 關聯的 taskscheduler ? ? ? ? ? ? task.factory.startnew(() => label1.text = "hello taskscheduler", cancellationtoken.none, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? taskcreationoptions.none, scheduler); }
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持碩編程。