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

c#synchronizationcontext以及send和post使用解读

 

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

 

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持硕编程

下一节:基于wpf制作一个可编程画板

c# 教程

相关文章