[C.C++] C# SynchronizationContext以及Send和Post使用解读

1593 0
王子 2023-5-12 08:59:59 | 显示全部楼层 |阅读模式
目录

    C# SynchronizationContext及Send和Post使用C#同步上下文SynchronizationContext学习笔记
      同步上下文的基本操作使用同步上下文来更新UI内容
    总结


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);
}
总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持中国红客联盟。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行