深入理解 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

最新文章

  1. 完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
  2. python的Template
  3. 第一个java程序hello world
  4. Java Debug调试简单方法--static使用
  5. 一次受限于操作系统进程数的OOM
  6. snoopy(强大的PHP采集类) 详细介绍
  7. File的文件提取的小练习
  8. Easy Number Challenge(暴力,求因子个数)
  9. java中关于窗体居中显示问题
  10. Url以.(点)结尾,在使用httpwebrequest读取的时候,微软会有一个bug……
  11. Java规范推荐
  12. Spring 自动装配及自动注册的相关配置
  13. 11个不常被提及的JavaScript小技巧
  14. [CF703D]Mishka and Interesting sum/[BZOJ5476]位运算
  15. Python——装饰器
  16. GitHub for Windows客户端使用操作流程
  17. 1022. Sum of Root To Leaf Binary Numbers从根到叶的二进制数之和
  18. “ORA-06550: 第 1 行, 第 7 列”解决方法
  19. 黄聪:FFmpeg 使用指南
  20. (拓扑)确定比赛名次 -- hdu -- 1285

热门文章

  1. ELK学习实验014:Nginx日志JSON格式收集
  2. Java 中 volatile 关键字及其作用
  3. docker命令补全
  4. SpringBoot 上传文件如何获取项目工程路径
  5. SpringBoot2 单元测试类的报错问题
  6. 安装了Python2.X和Python3.X后Python2.X IDLE打不开解决办法总结
  7. java并发编程工具类JUC第四篇:LinkedBlockingQueue链表队列
  8. selenium模拟不同浏览器的方式
  9. jupyter notebook 默认文件路径修改以及启动
  10. TVM性能评估分析(五)