首页 > 其他分享 >NET-SynchronizationContext

NET-SynchronizationContext

时间:2023-01-12 09:36:43浏览次数:64  
标签:上下文 代码 SynchronizationContext 线程 NET 执行 我们

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,这意味着如果我们将工作从一个线程池委托给另一个线程,我们可以获得当前运行环境的快照并将其传递给另一个线程

参考链接

  1. https://hamidmosalla.com/2018/06/24/what-is-synchronizationcontext/
  2. https://stackoverflow.com/questions/18097471/what-does-synchronizationcontext-do

标签:上下文,代码,SynchronizationContext,线程,NET,执行,我们
From: https://www.cnblogs.com/lizhenghao126/p/17045481.html

相关文章

  • NetCore模型绑定之FromBodyFromUriFromQueryFromRoute
    title:.NetCore模型绑定之FromBody、FromUri、FromQuery、FromRoutecategories:后端date:2022-10-2917:21:11tags:-.NETFromRoute[FromRoute]属性处理“?”之......
  • Asp-Net-Core-管道VS过滤器
    title:Asp.NetCore底层源码剖析(二)过滤器date:2022-09-1810:41:57categories:后端tags:-.NET正文Asp.NetCore中的过滤器有好几种,包括AuthorizationFilter、Ac......
  • Asp-Net-Core权限认证
    title:Asp.NetCore权限认证date:2022-10-2716:17:52tags:-.NET翻了很多的博客,文档,发现asp.netcore自带的权限认证还是比较复杂的,极少有哪篇文章把整个体系涉及......
  • AspNetCore底层源码剖析(三)IOC
    title:AspNetCore底层源码剖析(三)IOCdate:2022-09-2113:20:01categories:后端tags:-.NET介绍每个ASP.NETCore应用程序都有一个根级别的IServiceProvider,除......
  • AspNetCore管道
    title:Asp.NetCore底层源码剖析(一)中间件/管道categories:后端tags:-.NET当我们像下面这样添加一个管道时发生了什么?app.Use(async(httpcontext,next)=>{......
  • C#.NET制作DLL供DELPHI调用
    因为工作需求,本来想用C#做一个WebService,但是弄了两天没做成。于是想,反正都是我这一台电脑,做个DLL吧。1namespaceU8Service2{3publicinterfaceIMyFunc4......
  • 01. Kubernetes - 容器运行时(Container Runtime)
    背景2022年5月3日,Kubernetes1.24版本发布,正式移除对Dockershim的支持,这意味着Docker已经不能直接作为容器运行时运行在之后版本的Kubernetes中。此时就需要......
  • Kubernetes(k8s) kubectl 命令行工具的使用
    kubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并且能够在集群上进行容器化应用的安装与部署。本文主要介绍Kubernetes(k8s)kubectl命令......
  • Kubernetes HPA 的三个误区与避坑指南
    作者:之卫前言云计算带来的优势之一便是弹性能力,云原生场景下Kubernetes提供了水平弹性扩容能力(HPA),让应用可以随着实时指标进行扩/缩。然而HPA的实际工作情况可能和我......
  • Asp.Net自定义控件的开发
    基于Asp.Net的控件开发涉及到两种,一种是用户控件,即通过vs自带的服务器控件进行组合以开发需求,该类控件的开发相对简单;另一种是自定义控件,开发难度较高。1、在vs中新建......