C# SynchronizationContext以及Send和Post使用解讀
C# SynchronizationContext及Send和Post使用
1、(SynchronizationContext)同步上下文的作用
SynchronizationContext其實(shí)就是實(shí)現(xiàn)線程之間通訊的。
2、創(chuàng)建(SynchronizationContext)同步上下文的方法
- 1)直接new創(chuàng)建一個(gè)SynchronizationContext同步上下文對象。
- 2)winform程序通過SynchronizationContext.Current獲取UI線程的同步上下文對象。
- 3)AsyncOperation和AsyncOperationManager類來操作同步上下文對象,不直接訪問同步上下文對象(SynchronizationContext),推薦這程方法。
3、(SynchronizationContext)同步上下文的Send和Post方法
看了一些解釋Send和Post方法,感覺弄得很復(fù)雜,我感覺其實(shí)簡單來說,
- 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對象 ? ? ? ? ?//這個(gè)對象正在被創(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 一個(gè)同步消息調(diào)度到一個(gè)同步上下文。
SendOrPostCallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//TODO: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}; context.Send(callback,null);
- send調(diào)用后會(huì)阻塞直到調(diào)用完成。
- Post 將異步消息調(diào)度到一個(gè)同步上下文。
SendOrPostCallback callback = o => ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //TODO: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }; context.Post(callback,null);
和send的調(diào)用方法一樣,不過Post會(huì)啟動(dòng)一個(gè)線程來調(diào)用,不會(huì)阻塞當(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"; ? ? ? ? ? ? ? ? ? ? ? ?})); }
使用同步上下文也可以實(shí)現(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)建一個(gè)SynchronizationContext 關(guān)聯(lián)的 TaskScheduler ? ? ? ? ? ? Task.Factory.StartNew(() => label1.Text = "Hello TaskScheduler", CancellationToken.None, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TaskCreationOptions.None, scheduler); }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Unity編輯器預(yù)制體工具類PrefabUtility常用函數(shù)和用法
這篇文章主要為大家介紹了Unity編輯器預(yù)制體工具類PrefabUtility常用函數(shù)及用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08asp.net中調(diào)用oracle存儲(chǔ)過程的方法
存儲(chǔ)過程是在大型數(shù)據(jù)庫系統(tǒng)中,一組為了完成特定功能的SQL 語句集,存儲(chǔ)在數(shù)據(jù)庫中經(jīng)過第一次編譯后再次調(diào)用不需要再次編譯,用戶通過指定存儲(chǔ)過程的名字并給出參數(shù)來執(zhí)行它,下面給大家介紹下asp.net中調(diào)用oracle存儲(chǔ)過程的方法,需要的朋友可以參考下2015-08-08c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例分享
這篇文章主要介紹了使用c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例,需要的朋友可以參考下2014-02-02C#實(shí)現(xiàn)定義一套中間SQL可以跨庫執(zhí)行的SQL語句(案例詳解)
這篇文章主要介紹了C#實(shí)現(xiàn)定義一套中間SQL可以跨庫執(zhí)行的SQL語句,主要包括hisql查詢樣例、group by查詢、鏈?zhǔn)讲樵兗癶isql語句和鏈?zhǔn)讲樵兓煊玫膕ql語句,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07