C#SynchronizationContext以及Send和Post使用解讀
c#synchronizationcontext以及send和post使用解讀
c# synchronizationcontext及send和post使用
1、(synchronizationcontext)同步上下文的作用
synchronizationcontext其實就是實現(xiàn)線程之間通訊的。
2、創(chuàng)建(synchronizationcontext)同步上下文的方法
- 1)直接new創(chuàng)建一個synchronizationcontext同步上下文對象。
- 2)winform程序通過synchronizationcontext.current獲取ui線程的同步上下文對象。
- 3)asyncoperation和asyncoperationmanager類來操作同步上下文對象,不直接訪問同步上下文對象(synchronizationcontext),推薦這程方法。
3、(synchronizationcontext)同步上下文的send和post方法
看了一些解釋send和post方法,感覺弄得很復(fù)雜,我感覺其實簡單來說,
- 1)send方法就是同步調(diào)用,在當(dāng)前線程上調(diào)用委托。
- 2)post方法就是異步調(diào)用,在線程池中的線程調(diào)用委托。
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() ? ? ? ? { ? ? ? ? ?//獲取當(dāng)前synchronizationcontext非常重要對象在構(gòu)造函數(shù)中。我們想要的 ? ? ? ? ?//屬于線程的synchronizationcontext對象 ? ? ? ? ?//這個對象正在被創(chuàng)建。 ? ? ? ? ?//context= synchronizationcontext.current;當(dāng)前線程可能沒有synchronizationcontext對象;該線程尚未為設(shè)置synchronizationcontext對象。 ? ? ? ? ?//如果是這樣,我們可以通過創(chuàng)建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學(xué)習(xí)筆記
提供在各種同步模型中傳播同步上下文的基本功能。同步上下文的工作就是確保調(diào)用在正確的線程上執(zhí)行。
同步上下文的基本操作
current 獲取當(dāng)前同步上下文
var context = synchronizationcontext.current;
send 一個同步消息調(diào)度到一個同步上下文。
sendorpostcallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//todo: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}; context.send(callback,null);
- send調(diào)用后會阻塞直到調(diào)用完成。
- post 將異步消息調(diào)度到一個同步上下文。
sendorpostcallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //todo: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }; context.post(callback,null);
和send的調(diào)用方法一樣,不過post會啟動一個線程來調(diào)用,不會阻塞當(dāng)前線程。
使用同步上下文來更新ui內(nèi)容
無論winfroms和wpf都只能用ui線程來更新界面的內(nèi)容
常用的調(diào)用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"; ? ? ? ? ? ? ? ? ? ? ? ?})); }
使用同步上下文也可以實現(xiàn)相同的效果,winfroms和wpf繼承了synchronizationcontext,使同步上下文能夠在ui線程或者dispatcher線程上正確執(zhí)行
system.windows.forms. windowsformssynchronizationcontext system.windows.threading. dispatchersynchronizationcontext
調(diào)用方法如下:
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); //調(diào)用 }
使用.net4.0的task 可以簡化成
private void button_click(object sender, eventargs e) { ? ? ? ? ? ? var ?scheduler = taskscheduler.fromcurrentsynchronizationcontext(); // 創(chuàng)建一個synchronizationcontext 關(guān)聯(lián)的 taskscheduler ? ? ? ? ? ? task.factory.startnew(() => label1.text = "hello taskscheduler", cancellationtoken.none, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? taskcreationoptions.none, scheduler); }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持碩編程。