NET-SynchronizationContext
title: .NET SynchronizationContext
date: 2022-12-06 09:38:53
tags:
- .NET
前言
最近在看CAP的源码,经常能看到ConfigureAwait(false),例如下面这一段:
public async Task PublishAsync(string stream, NameValueEntry[] message)
{
await ConnectAsync()
.ConfigureAwait(false);
await _redis!.GetDatabase().StreamAddAsync(stream, message)
.ConfigureAwait(false);
}
不明白这一句话的意义,于是乎查了一下资料,这里记录总结一下
SynchronizationContext是什么
先看一下MSDN上官方的解释:
SynchronizationContext是一个基类,它提供了没有同步的线程自由的上下文。实现了这个类的同步模型的类允许公共语言运行时内部的异步/同步操作能够在合适的同步模型上允许。该模型还简化了托管应用程序必须遵循的一些需求,以便在不同的同步环境下正确工作。同步模型的提供者可以扩展这个类,并为这些方法提供他们自己的实现。
链接:https://learn.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext?view=net-7.0
听起来非常的官方,但是上面这句话的大体意思是想说不同的框架在线程之间的通信方式不同,我们可能想要在正确的上下文中调用特定的代码,比如WPF中的Dispatcher.BeginInvoke允许我们从另一个线程调用UI线程来执行具体的代码,SynchronizationContext类就是这些实现的一个抽象类,它提供了一些方法,让我们可以在不同的上下文中执行代码。
SynchronizationContext公开了几个方法,我们可以通过这些方法来实现不同的上下文之间的通信,其中比较重要的一个方法就是Post,它的定义如下:
public virtual void Post(SendOrPostCallback d, object? state);
这个方法的作用是将一个委托放入队列中,然后在合适的时候执行,默认的实现是通过ThreadPool.QueueUserWorkItem来实现的,也就是说,这个方法的默认实现是将委托放入线程池中,然后在合适的时候执行。但是,我们可以通过继承SynchronizationContext类来实现自己的同步上下文,然后重写Post方法来实现不同的同步上下文,比如WPF中的DispatcherSynchronizationContext就是通过重写Post方法来实现的,调用方式就是通过调用Dispatcher.BeginInvoke来实现。
从名字上来看,SynchronizationContext是我们当前代码运行的一个上下文环境,也就是说在异步程序中,当我们把一段业务代码委托给另一个线程执行时,我们捕获了当前的上下文环境,放到SynchronizationContext中,然后把它放到了Task对象上,重点是我们可以捕获当前环境并传递给另一个线程,这样我们可以在另一个线程中恢复当前的上下文环境,然后执行我们的代码。
为什么需要SynchronizationContext?
有时候我们需要在另一个线程中执行一段代码,比如我们需要在另一个线程中更新UI,这时候我们就需要在另一个线程中恢复当前的上下文环境,然后执行我们的代码,这就是SynchronizationContext的作用。
具体原因这里不细说,了解WPF、Winform应该都知道UI控件的属性只能在UI线程更新
不是所有的框架都有SynchronizationContext
不是所有的框架都有SynchronizationContext,比如Asp.Net Core就没有,参考 https://stackoverflow.com/questions/18097471/what-does-synchronizationcontext-do
所以有些时候我们会发现在很多开源框架内都会使用ConfigureAwait(false)来禁用SynchronizationContext,这样做的目的就是为了避免在不同的上下文中执行代码,比如在Asp.Net Core中,我们不需要在另一个线程中恢复当前的上下文环境,因为Asp.Net Core没有SynchronizationContext,所以我们可以使用ConfigureAwait(false)来禁用SynchronizationContext,这样做的好处是可以提高性能,因为不需要在不同的上下文中执行代码。
同时需要注意的是,async await默认会捕获当前的运行上下文,如果上下文为空的话,则默认会在
TaskScheduler.Default上执行,也就是在线程池内的任意一个线程执行,当然这个线程也有可能是UI线程或执行它的线程
每个线程都有一个SynchronizationContext
每个线程都有一个SynchronizationContext,这意味着如果我们将工作从一个线程池委托给另一个线程,我们可以获得当前运行环境的快照并将其传递给另一个线程
参考链接
- https://hamidmosalla.com/2018/06/24/what-is-synchronizationcontext/
- https://stackoverflow.com/questions/18097471/what-does-synchronizationcontext-do
NET-SynchronizationContext的更多相关文章
- 线程处理模型 由于 SynchronizationContext 引起的死锁问题解决
由于GUI 应用程序 不能使用线程池的线程更新UI,只能使用 GUI 线程更新,所以在 await 前后需要保证是同一个 GUI 线程 ASP.NET 程序 的线程处理客户端请求的时候,需要假定客户端 ...
- 搞懂 SynchronizationContext(第一部分)【翻译】
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- 搞懂 SynchronizationContext
SynchronizationContext -MSDN 很让人失望 我不知道为什么,目前在.Net下关于这个类只有很少的资料.MSDN文档也只有很少的关于如何使用SynchronizationCon ...
- 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute
[源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...
- 【C#】【Thread】SynchronizationContext线程间同步
SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯. 需要注意的是,不是每个线程都附加SynchronizationContext这个对象, ...
- SynchronizationContext的研究之一(非WPF及Forms)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- SynchronizationContext一篇
SynchronizationContext context; 最近写代码用到了这个,特别记录一下. 作用如下: // 摘要: // 提供在各种同步模型中传播同步上下文的基本功能. public cl ...
- 译文: async/await SynchronizationContext 上下文问题
async / await 使异步代码更容易写,因为它隐藏了很多细节. 许多这些细节都捕获在 SynchronizationContext 中,这些可能会改变异步代码的行为完全由于你执行你的代码的环境 ...
- 理解SynchronizationContext,如何在Winform里面跨线程访问UI控件
SynchronizationContext 类是一个基类,可提供不带同步的自由线程上下文. 此类实现的同步模型的目的是使公共语言运行库内部的异步/同步操作能够针对不同的异步模型采取正确的行为.此模型 ...
- 【.NET异步编程系列2】掌控SynchronizationContext避免deadlock
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要去学习,贴心的.NET提供Task线程包装类和await/async异步编程语法糖简化了异步编程方式. 相信很多开发者都看到如下异步编程实践原 ...
随机推荐
- 4.websocket基本概念
websockey的模式就是在于当前端向后端发送请求创建一个websocket链连接之后,连接默认不断开,前端和服务端就维护了一个连接,前端可以通过连接给服务端发消息,服务端也可以通过连接给前端发消息 ...
- 【原创】i.MXRT J-Flash烧写算法使能eFuse熔丝位写入
临近年底,终于又憋了一篇文章出来,本来年初的时候是有计划把去年总结的一些东西整理下发布出来的,结果还是被工作和生活上各种琐事给耽搁了.哎,今年刚过了自己35岁的生日,眼瞅着这个人生节点 ...
- POC、EXP、SRC概念厘清
「POC」 POC可以看成是一段验证的代码,就像是一个证据,能够证明漏洞的真实性,能证明漏洞的存在即可. https://zhuanlan.zhihu.com/p/26832890 「EXP」 ...
- 基于LZO的高性能无损数据压缩IP
LZOAccel-C LZO Data Compression Core/无损数据压缩IP Core LZOAccel-C是一个无损数据压缩引擎的FPGA硬件实现,兼容LZO 2.10标准. Core ...
- 几个实用 shell 脚本
1. Dos攻击防范(自动屏蔽攻击 IP) #!/bin/bash DATE=$(date +%d/%b/%Y:%H:%M) LOG_FILE=/usr/local/nginx/logs/demo2. ...
- Rust Aya 编写 eBPF 程序
本文地址:https://www.ebpf.top/post/ebpf_rust_aya 1. 前言 Linux 内核 6.1 版本中有一个非常引人注意的变化:引入了对 Rust 编程语言的支持.Ru ...
- tools2
[对身份证的校验] //身份证的校验 import java.util.stream.IntStream; /** * 身份证号码验证 * 1.号码的结构 * 公民身份号码是特征组合码,由十七位数字本 ...
- 质数之和【计算第x个到第y个质数之和】
题目:质数之和 已知,第一个质数是2,第二个质数是3,第三个质数是5,第四个质数是7,第五个质数是11,第六个质数是13,第七个质数是17,输入两个不相等的正整数a和b,求出第a个质数到第b个质数当中 ...
- Oracle中新建数据表的两种方法
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...
- Go语言核心36讲35
到目前为止,我们已经一起学习了Go语言标准库中最重要的那几个同步工具,这包括非常经典的互斥锁.读写锁.条件变量和原子操作,以及Go语言特有的几个同步工具: sync/atomic.Value: syn ...