C# SynchronizationContext以及Send和Post使用解读
(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun)
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); }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持程序员之家。
最新评论