zoukankan      html  css  js  c++  java
  • ExecutionContext & SynchronizationContext

    最近在研究.net4.5中的有关异步编程的新特性,从自己Google Reader 订阅的一些博客中接触到了两个很陌生的单词ExecutionContext和SynchronizationContext,于是仔细研究了一下,记录下来备忘。
    什么是ExecutionContext
    在许多系统中thread-local storage(TLS)线程本地存储记录了正在运行的当前环境或者上下文的一些信息,而在CLR中ExecutionContext做了类似的事情.在同步的世界中,所有的一切都发生在当前线程内,线程内有关的所有数据对其内所有代码可见,也同时被所有代码所操纵影响.也就是说假设有方法ABC在当前线程内顺序执行,当前线程环境的一切信息对ABC都是可见的,同时ABC又影响着这些当前线程环境.但是在异步的世界情况变了,还假设有方法ABC,这三个方法有可能运行在不同的线程中,ABC三者是相互见不到对方线程信息的,所以需要在每个异步点传递当前线程环境信息到另一个线程中,另一个线程中的方法才能访问该线程中数据信息并且修改这些信息.完成这个任务就需要ExecutionContext记录当前线程环境然后再另一个线程中restore出来. 情况类似于这样:

    // 记录当前的环境信息到ec, 这些信息会在委托调用时通过静态的方法Run恢复出来
    ExecutionContext ec = ExecutionContext.Capture(); 
    
    
    ExecutionContext.Run(ec, delegate 
    { 
    … // 在这的代码就能看见ec中的环境信息了。
    }, null);

    在.Net FrameWork中所有处理异步情况的方法都会通过类似的方法Capture/Restore ExecutionContext(不包括unsafe代码),比如Task.Run,ThreadPool.QueueUserWorkItem,Delegate.BeginInvoke,Stream.BeginRead,DispatcherSynchronizationContext.Post 

    比如Task.Run,当我们调用Run时,背后所做的事就是ExecutionContext.Capture()捕获当前线程环境,然后在Run中的delegate方法执行的时候把环境还原。

    什么是SynchronizationContext

    程序员都很热衷与抽象,对硬编码深恶痛绝,分层和抽象会为我们日后维护和扩展系统带来极大的便利,这也就是为什么会有接口,抽象类,和虚方法。而SynchronizationContext也是一种抽象。打个比方,当我们编写WinForm程序时,为避免后台处理海量数据带来的UI界面假死状态,通常会重开线程或者将这些工作放入线程池等,任务完成之后把处理的结果封送返回给UI线程时,通常会用Control.BeginInvoke方法。但是这种情况如果发生在WPF和Silverlight程序中呢,封送处理又得用Dispatcher.BeginInvoke或者InvokeAsync.ASP.Net又是另一种情况。于是我们使用了不同了方法完成了相同的动作,那么对于不同的UI框架我们怎么处理这些相同事件呢?于是抽象的想法来了,这就是SynchronizationContext。它提供了一个虚方法Post(),这个方法会接收委托方法并且执行它。而对于WinForm的情况会提供WinFormSynchronizationContext,它会覆盖掉虚方法Post(),并且在子类中Post()调用Control.BeginInvoke;对于WPF或者Silverlight,会提供子类DispatcherSynchronizationContext,同样覆盖掉虚方法Post(),并且在子类Post中调用Dispatcher.Run。

    public static void DoWork(Control c) 
    { 
    ThreadPool.QueueUserWorkItem(delegate 
        { 
    ..... c.BeginInvoke(delegate { .....//对UI的操作 }); }); } 如果替换成SynchronizationContext去写就成了这样: public static void DoWork(SynchronizationContext sc) { ThreadPool.QueueUserWorkItem(delegate { … // do work on ThreadPool sc.Post(delegate { … // do work on UI }, null); }); }
    或者如下
    public static void DoWork() { var sc = SynchronizationContext.Current; ThreadPool.QueueUserWorkItem(delegate { … // do work on ThreadPool sc.Post(delegate { … // do work on the original context }, null); }); }

    ExecutionContext VS SynchronizationContext

    对比两者你会发现它们都会在异步操作时捕获当前线程环境上下文,但后续操作不一样,ExecutionContext会调用delegate方法并在执行时在另一个线程中恢复该线程环境状态。而SynchronizationContext仅仅是用当前捕获的环境信息去调用委托方法,这个委托方法怎么什么时候执行,在哪执行,怎么执行都取决于底层的具体实现。

    注意:

     以下CodeProject文章中有一点讲得不太准确,根据惯例,如果一个线程的当前 SynchronizationContext 为 null,那么它隐式具有一个默认 SynchronizationContext。默认 SynchronizationContext 将其异步委托列队到 ThreadPool,但在调用线程上直接执行其同步委托。因此,其上下文包含所有 ThreadPool 线程以及调用 Send 的任何线程。此上下文“借用”调用 Send 的线程,将它们放入其上下文,直至委托完成。从这种意义上讲,默认上下文可以包含进程中的所有 线程。所以UI应用程序通常有两个同步上下文,一个是UI线程的SynchronizationContext,另一个是包含ThreadPool线程的默认SynchronizationContext。

    一般遇到疑问,首先去百度国内论坛,但是继而回去CodeProject相关文章去佐证,好多文章都是从Codeproject上翻译或者浓缩出来的,但这次事件我才发现CodeProject上文章也不靠谱,虽然那上边有好多微软MVP和其他大公司的技术人员,微软的东西还是得去MSDN blog或者 MSDN Magzine上比较靠谱,尤其是看到Anders Hejlsberg, Stephen Toub, Erick Lippert, Herb Sutter审阅,就知道这是质量的保证。备忘完毕,还有半天时间,接着去深挖这块东西。

    reference:
    http://blogs.msdn.com/b/pfxteam/archive/2012/06/15/executioncontext-vs-synchronizationcontext.aspx
    http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I
    http://msdn.microsoft.com/zh-cn/magazine/gg598924.aspx
    http://msdn.microsoft.com/zh-cn/magazine/hh456402.aspx

  • 相关阅读:
    VxWorks 6.9 内核编程指导之读书笔记 -- POSIX
    VxWorks 6.9 内核编程指导之读书笔记 -- ISRs和Watchdog Timer
    VxWorks 6.9 内核编程指导之读书笔记 -- Singnals
    VxWorks 6.9 内核编程指导之读书笔记 -- 多任务
    VxWorks 6.9 内核编程指导之读书笔记 -- 多任务(二)
    VxWorks 6.9 内核编程指导之读书笔记 -- C++开发
    VxWorks 6.9 内核编程指导之读书笔记 -- VxWorks Kernel application (二)
    VxWorks 6.9 内核编程指导之读书笔记 -- VxWorks kernel application (一)
    发布ASP(非.Net)网站
    解决方法:An error occurred on the server when processing the URL. Please contact the system administrator
  • 原文地址:https://www.cnblogs.com/salomon/p/2567339.html
Copyright © 2011-2022 走看看