当前位置 : 主页 > 网络编程 > c#编程 >

C#SynchronizationContext以及Send和Post使用解读

来源:互联网 收集:自由互联 发布时间:2023-05-16
目录 C# SynchronizationContext及Send和Post使用 C#同步上下文SynchronizationContext学习笔记 同步上下文的基本操作 使用同步上下文来更新UI内容 总结 C# SynchronizationContext及Send和Post使用 1、(Synchro
目录
  • 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);
    }

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

    网友评论