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方法,感覺弄得很復雜,我感覺其實簡單來說,
- 1)Send方法就是同步調(diào)用,在當前線程上調(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()
? ? ? ? {
? ? ? ? ?//獲取當前SynchronizationContext非常重要對象在構(gòu)造函數(shù)中。我們想要的
? ? ? ? ?//屬于線程的SynchronizationContext對象
? ? ? ? ?//這個對象正在被創(chuàng)建。
? ? ? ? ?//context= SynchronizationContext.Current;當前線程可能沒有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學習筆記
提供在各種同步模型中傳播同步上下文的基本功能。同步上下文的工作就是確保調(diào)用在正確的線程上執(zhí)行。
同步上下文的基本操作
Current 獲取當前同步上下文
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)用,不會阻塞當前線程。
使用同步上下文來更新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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
WPF+WriteableBitmap實現(xiàn)高性能曲線圖的繪制
這篇文章主要為大家詳細介紹了如何利用WPF+WriteableBitmap實現(xiàn)高性能曲線圖的繪制,文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下2022-08-08
在C#中如何使用正式表達式獲取匹配所需數(shù)據(jù)
本文給大家分享C#中如何使用正式表達式獲取匹配所需數(shù)據(jù) ,非常實用,對正則表達式獲取匹配相關(guān)知識感興趣的朋友一起學習吧2016-03-03
詳解如何獲取C#類中發(fā)生數(shù)據(jù)變化的屬性信息
這篇文章主要介紹了詳解如何獲取C#類中發(fā)生數(shù)據(jù)變化的屬性信息,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05
C#實現(xiàn)把txt文本數(shù)據(jù)快速讀取到excel中
這篇文章主要介紹了C#實現(xiàn)把txt文本數(shù)據(jù)快速讀取到excel中,本文直接給出示例代碼,需要的朋友可以參考下2015-06-06

