• 深入理解 SynchronizationContext


    深入理解 SynchronizationContext

    SynchronizationContext(后续以SC简称) 是什么?

    1.1 概念

    ​ 在 .NET 框架的多线程程序中,往往很多时间需要将一个线程工作单元或上下文,传递给另一个线程。我们都知道的是 Windows 上的程序是以 消息循环为中心的,这个如何理解呢?

    每一个 window 窗体都有一个与之关联的 Window Procedure,这个是一个用来处理所有消息发送或发送到类的给所有消息的函数。窗体的所有UI显示和显示都取决于 Window Procedure 对这些消息的响应。

    SynchronizationContext 主要提供了一下三方面的功能:

    ​ 1) 提供了一种把工作单元 添加到 上下文的队列中的方法。

    ​ 2) 每一个线程 都有 一个 “current” 的 上下文。

    ​ 3) 它保存着未完成异步操作数的计数,这个数量 随着 当前的 SC 被捕获,或被夺取时增加,当捕获的 SC 用于将完成通知排队发送到该上下文时,则减少。

    // 重要的 SynchronizationContext APIClass
    {
      // Dispather work to the context.
      void Post(); // Asynchronously
      void send(); // Synchronously
      
      // Keep track of the number of asynchronous operations.
      void OperationStarted();
      void OperationCompleted();
      
      // Each thread has a current context.
      // If "Current" is null, then the thread's current context is
      // "new SynchronizationContext()", by convention.
      static SynchronizationContext Current{get;}
      static void SetSynchronizationContext(SynchronizationContext);
    }
    

    1.2 SynchronizationContext 的实现

    1)WindowsFormsSynchronizationContext (System.Windows.Forms.dll)

    ​ 1,Use ISynchronizeInvoke on UI Control,用来将委托传递 给 win32 message loop

    ​ 2,每一个 UI 线程 都会创建一个 WindowsFormsSynchronizationContext

    ​ 3,WindowsFormsSynchronizationContext 的上下文是一个 单一的UI 线程

    2)DispatcherSynchronizationContext(WindowsBase.dll: System.Windows.Threading)

    ​ 1,以 “Normal” 优先级的委托 传递给 UI 线程。

    ​ 2,所有排队到 DispatcherSynchronizationContext 的委托都是由 特定的UI线程 按照他们排队的顺序 依次执行,一次执行一个。

    ​ 3,DispatcherSynchronizationContext 的上下文是一个 单一的 UI 线程

    3)Default(ThreadPool) SynchronizationContext(mscorlib.dll: System.Threading)

    ​ 1,默认的 SynchronizationContext 是一个默认构造函数的 SynchronizationContext 对象,按照惯例,如果一个线程 当前的 SynchronizationContext 是 null,那么它会 隐式的 含有一个 默认的 SynchronizationContext

    ​ 2,默认 SynchronizationContext 将它的异步委托 添加到 线程池 队列,但是 在调用的线程上执行它的同步委托。因此,它的上下文 涵盖了 所有的线程池的线程 以及 调用它的线程。上下文 “借用” 调用它的线程,然后把它们带入到上下文中 直到委托结束。从某种意义上来说,默认上下文可能包含当前进程中的任何线程。

    ​ 3,默认 SynchronizationContext 是应用在 线程池中的线程的除非是被 ASP.NET 托管的代码,默认的 SynchronizationContext 也隐式应用于显式的子线程中除非子线程设置了自己的 SynchronizationContext。因此,UI 的应用一般都有两个 SynchronizationContext, UI 的 SynchronizationContext cover UI thread, default SynchronizationContext cover ThreadPool thread。

    图1 是一个典型比如 WPF 程序,调用 Dispatcher.InvokeDispatcher.BeginInvoke 时Context 转换的一个图。

    private void On_Time_Elapsed(object sender, EventArgs e)
    {
    		Dispatcher.Invoke(()=>{
          _displayTextBlock.Text = "Show Here.";
        });  
    }
    

    图1

    图2 是 WPF 程序中,Dispatcher.Invoke 中又新开了线程池的线程执行的例子。

    private void On_Time_Elapsed(object sender, EventArgs e){
      Dispatcher.Invoke(()=>{
     			Task.Run(()=>{
            // Do Something here.
          });   
        
        _displayTextBlock.Text = "1111";
      });
    }
    

    图2

    各个不同实现的 SynchronizationContext 的区别

    Specific Thread Used to Execute Delegates Exclusive (Delegates Execute One at a Time) Ordered (Delegates Execute in Queue Order) Send May Invoke Delegate Directly Post May Invoke Delegate Directly
    Windows Forms Yes Yes Yes If called from UI thread Never
    WPF/Silverlight Yes Yes Yes If called from UI thread Never
    Default No No No Always Never
    ASP.NET No Yes No Always Always

    参考

    1) It's all about SynchronizationContext

  • 相关阅读:
    P4365 [九省联考2018]秘密袭击coat
    P3705 [SDOI2017]新生舞会 01分数规划+费用流
    P4313 文理分科 最小割
    P1707 刷题比赛
    P3994 高速公路 树形DP+斜率优化+二分
    P3384 【模板】树链剖分
    P4915 帕秋莉的魔导书
    P3690 【模板】Link Cut Tree (动态树)
    P3615 如厕计划
    loj #2538. 「PKUWC2018」Slay the Spire
  • 原文地址:https://www.cnblogs.com/xiyin/p/15004355.html
Copyright © 2020-2023  润新知