看过这么多爆文,依旧走不好异步编程这条路?​

点击蓝字

关注我们

本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext。

引言

C#异步编程语法糖async/await,使开发者很容易就能编写异步代码。
零散看过很多文章,很多是填鸭式灌输 (有的翻译文还有偏差)。

遵守以上冷冰冰的②③条的原则,一般可确保异步程序按预期运作,

我们时常能在各大论坛看到同学们(因不遵守②③点)引发的死锁现场。

由async/await引起的死锁现场

UI程序(WinForm、WPF):点击按钮,触发一个HTTP请求,用请求结果修改UI控件,以下代码会引发deadlock

public static async Task<string> GetJsonAsync(Uri uri)
{using (var client = new HttpClient()){var jsonString = await client.GetStringAsync(uri);return jsonString;}
}// 上层调用方法
public void Button1_Click(...)
{var jsonTask = GetJsonAsync(...);textBox1.Text = jsonTask.Result;
}

ASP.NET web程序:从api接口发起HTTP请求,返回请求的结果,以下代码也会引发deadlock

public static async Task<string> GetJsonAsync(Uri uri)
{using (var client = new HttpClient()){var jsonString = await client.GetStringAsync(uri);return jsonString;}
}
// 上层调用方法
public class MyController : ApiController
{public string Get(){var jsonTask = GetJsonAsync(...);return jsonTask.Result;}
}

☺️ 解决以上死锁有两种编程方式:

  1. 不再混用异步/同步写法, 始终使用async/await语法糖编写异步代码

  2. 对等待的异步任务应用ConfigureAwait(false)方法

SynchronizationContext就是这类死锁的牛鼻子,大多数时候SynchronizationContext是在异步编程后默默工作,但了解这个对象对于理解sync/await工作原理、解决死锁大有裨益。

本文会解释:

  1. async/await工作机制

  2. SynchronizationContext在异步编程语法糖中的意义

  3. 示例代码为什么会deadlock

1.  await/async语法糖工作机制

微软提出Task线程包装类、 await/async语法糖简化了异步编程的方式:

第②步:调用异步方法GetStringAsync时,开启异步任务;

第⑥步:遇到await关键字,框架会捕获调用线程的同步上下文(SynchronizationContext)对象, 附加给异步任务;同时控制权上交到上层调用函数;

第⑦步:异步任务完成,通过IO完成端口通知上层线程, 第⑧步:通过捕获的线程同步上下文执行后继代码块;

2. SynchronizationContext的意义

先看下MSDN中关于SynchronizationContext的定义:

提供在各种同步模型中传播同步上下文的基本功能。此类实现的同步模型的目的是允许公共语言运行库的内部异步/同步操作使用不同的同步模型正常运行。

☹️这就不是人能看懂的解释,我给出的解释是:在线程切换过程中保存调用线程的上下文环境, 用于在异步任务完成后使用此线程同步上下文执行后继代码。

线程同步上下文的意义在哪?

大家都知道:WinForm和WPF都有类似的原则:长耗时的任务在后台进行,将异步结果返回给UI线程 。(这难道就是ConfigureAwait方法默认传true的原因?)

此时就需要捕获UI线程的SynchronizationContext,并将这个对象传入异步任务。

public static void DoWork()
{//On UI threadvar sc = SynchronizationContext.Current;ThreadPool.QueueUserWorkItem(delegate{//... async task:do work on ThreadPool        sc.Post(delegate{// do work on the original context (UI)}, null);});
}

SynchronizationContext表示代码运行的线程环境,在异步编程中,利用该对象切换代码执行环境。

不同的.NET框架因各自独特的线程切换场景有不同的SynchronizationContext子类(重写父类虚方法):

  • ASP.NET有AspNetSynchronizationContext

  • WinForm有WindowsFormSynchronizationContext

  • WPF 有DispatcherSynchronizationContext

  • ASP.NET Core、控制台程序不存在SynchronizationContext,SynchronizationContext.Current=null

AspNetSynchronizationContext维护了HttpContext.Current、用户身份和文化,但在ASP. NET Core这些信息天然依赖注入,故不再需要SynchronizationContext;另一个好处是不再获取同步上下文对性能也是一种提升。

因此,对于ASP.NET Core程序,ConfigureAwait(false)不是必需的,然而,在基础库时最好还是使用ConfigureAwait(false),因为你保不准上层会混用同步/异步代码。

3. 引言代码为什么发生deadlock

观察引言代码,控制权返回到上层调用函数时,执行流使用Result/(Wait方法)等待任务结果:Result/Wait()导致调用线程同步阻塞(等待任务完成), 而异步任务执行完成后,会尝试利用捕获的同步上下文执行后继代码,这样形成死锁。

正因为如此,我们提出两种方式解决死锁:

  • 原调用函数始终使用await方法,这样调用线程是异步等待任务完成,后继代码可以在该线程同步上下文上执行

  • 对异步任务应用ConfigureAwait(false)方法

ConfigureAwait(bool):true  表示尝试在捕获的原调用线程SynchronizationContext 中执行后继代码;false 不再尝试在捕获的线程SynchronizationContext中执行后继代码。 ConfigureAwait(false)  能解决[因调用线程同步阻塞]引发的死锁,但是同步阻塞没有利用异步编程的优点,不是很推荐。

归根到底,这两种解决死锁的方式都是针对SynchronizationContext
ASP. NET Core和控制台程序,因为捕获的SynchronizationContext=null, 会选择一个线程同步上下文来执行,不会死锁。

总结

微软为加快开发效率上着实费了心力,.NET提供的await/async语法糖简化了异步编程方式,

在异步编程中,SynchronizationContext决定了后继代码在哪里执行的环境,深入理解这个对象的背景和不同框架的实现方式,能帮助我们避免编写死锁代码。

# 更多精彩

  • 面试八股文:你写过自定义任务调度器吗?

  • 你管这叫"线程安全"?

  • 墙裂推荐:这可能是CAP理论的最好解释

  • 全网最通透的“闭包”认知 · 跨越语言

  • 鹅厂二面,Nginx回忆录

  • 实话实说:只会.NET,会让我们一直处于鄙视链、食物链的下游

  • 什么是云原生?

今天因为你的点赞,让我元气满满!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302046.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用html制作篮球网页,篮球网站的设计与实现).doc

篮球网站的设计与实现)篮球网站的设计与实现摘要关键词AbstractBasketball net is an introductory history of basketball, basketball to promote the development and understanding of the status quo of modern basketball, the website with news, pictures, mainly. Inc…

Android获取设备已安装的应用

2019独角兽企业重金招聘Python工程师标准>>> 项目中&#xff0c; 我们经常要用到显示系统已安装的应用&#xff0c; 可以通过两种方式获取已安装的应用&#xff0c; 一种是通过ApplicationInfo, 一种是通过ResolveInfo. 这里用的是ResolveInfo, 上代码。 <!-- la…

html按钮圆弧样式,几款不错的按钮样式汇总

几款不错的按钮样式汇总在网页设计中按钮一般默认的都比较“丑”&#xff0c;能不能通过一些好的样式来设计呢&#xff0c;下面提供几款不错的按钮样式&#xff0c;希望对大家有所帮助。一、带图标的按钮按钮样式截图按钮样式代码如下&#xff1a;/* CSS Document *//* BUTTONS…

如何讲页面打入jar包中_如何把我的Java程序变成exe文件?

JAVA是一种“跨平台”的语言&#xff0c;拥有“一次编写&#xff0c;处处运行”的特点&#xff0c;让它成为当今IT行业&#xff0c;必不可少的一门编程语言。每一个软件开发完成之后&#xff0c;应该大家都需要打包程序并发送给客户&#xff0c;常见的方式&#xff1a;java程序…

Api网关Kong集成Consul做服务发现及在Asp.Net Core中的使用

&#xfeff;1622219047536写在前面Api网关我们之前是用 .netcore写的 Ocelot的&#xff0c;使用后并没有完全达到我们的预期&#xff0c;花了些时间了解后觉得kong可能是个更合适的选择。简单说下kong对比ocelot打动我的&#xff1a;1、kong可以直接代替Nginx/OpenRestry做前端…

view 背景透明

引用&#xff1a;http://www.eoeandroid.com/thread-37112-1-1.html surfaceView.setZOrderOnTop(true);surfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);win.setBackgroundColor(255);

女生学高铁和计算机哪个更好,2020铁路最好的5个专业 女生上铁路学什么专业好...

铁路专业一直是比较受欢迎的&#xff0c;有些同学都想学习铁路专业&#xff0c;应为一旦找到和铁路相关的工作&#xff0c;工资待遇都是非常好的&#xff0c;但是铁路里面也不是所有的专业都非常好&#xff0c;那么铁路里面最好的专业有哪些呢&#xff1f;女生适合学习铁路的哪…

ML.NET Cookbook:(10)如何使用模型做出一个预测?

因为任何ML.NET模型都是一个转换器&#xff0c;所以您当然可以使用model.Transform将该模型应用于“数据视图”并以这种方式获得预测。不过&#xff0c;更典型的情况是&#xff0c;没有我们想要预测的“数据集”&#xff0c;而是一次只接收一个样本。例如&#xff0c;我们将模型…

裤子换裙子,就问你GAN的这波操作秀不秀

全世界只有3.14 % 的人关注了数据与算法之美把照片里的绵羊换成长颈鹿、牛仔长裤换成短裙。听起来有点不可思议&#xff0c;但韩国科学技术院和浦项科技大学的研究人员目前已实现了这一骚操作。他们开发的一种机器学习算法可在多个图像数据集上实现这种操作。其论文《InstaGAN:…

python中字典长度可变吗_python中列表长度可变吗

python中列表长度可变吗&#xff1f;下面给大家介绍一下python中可变和不可变的类型&#xff1a;可变、不可变可变/不可变类型,指的是&#xff1a;内存id不变&#xff0c;type也不变的前提下&#xff0c;value是否是可变的。int()和str()都是不可变类型列表、字典是可变类型对于…

Windows UI风格的设计(11)

转载于:https://blog.51cto.com/8382359/1342271

教之初计算机考试函数应用题,教之初计算机考试系统

教之初计算机考试系统官方版是一款发布长达12年之久的免费考试系统软件&#xff0c;已经有数千万次使用的软件。教之初考试系统是专业的考试软件&#xff0c;您所考虑的功能&#xff0c;教之初都已经非常贴心地替您想好&#xff0c;如果您发现需要的功能并不存在&#xff0c;那…

这里聚集了优秀的数学老师、家长,有超多惊喜在等你!

全世界有3.14 % 的人已经关注了数据与算法之美今天的这篇文章&#xff0c;是向大家推荐一个数学公众号“少年数学家”。“少年数学家”是一个致力为数学老师与家长&#xff0c;提供丰富的数学课外知识、数学人物、数学趣谈、科技与数学的公众号&#xff0c;希望通过这些万物背后…

ASP.NET Core文件上传IFormFile于Request.Body的羁绊

前言在上篇文章深入探究ASP.NET Core读取Request.Body的正确方式[1]中我们探讨了很多人在日常开发中经常遇到的也是最基础的问题&#xff0c;那就是关于Request.Body的读取方式问题&#xff0c;看是简单实则很容易用不好。笔者也是非常荣幸的得到了许多同学的点赞支持&#xff…

librosa能量_语音MFCC提取:librosa amp;amp; python_speech_feature(2019.12)

最近在阅读语音方向的论文&#xff0c;其中有个被提及很多的语音信号特征MFCC(Mel-Frequency Cepstral Coefficients)&#xff0c;找到了基于python的语音库librosa(version0.7.1)和python_speech_features(version0.6)&#xff0c;下文对这两个库计算MFCC的流程细节稍作梳理。…

线性代数与矩阵论 习题 1.2.2

试利用辗转相除法&#xff0c;求有理系数多项式$u(x)$和$v(x)$,使得$u(x)f(x)v(x)g(x)(f(x),g(x))$. (1)$f(x)3x^3-2x^2x2$,$g(x)x^2-x1$. 解:\begin{align*} 3x^3-2x^2x2&3x(x^2-x1)(x^2-2x2)\\x^2-x1&(x^2-2x2)(x-1)\\x^2-2x2&x(x-1)-(x-2)\\x-1&x-21\\\end{…

Uno 平台 一 WinUI终极跨平台方案(一)

以下是 Uno 平台的官方介绍&#xff1a;关于 Uno 平台Uno平台能够创建像素级完美的&#xff0c;只通过C#XAML编写的应用程序&#xff0c;能够跨平台运行在Windows&#xff0c;iOS&#xff0c;安卓&#xff0c;macOS&#xff0c;Linux和Web上&#xff0c;Uno 平台是免费和开源的…

Python程序员的30个常见错误

全世界只有3.14 % 的人关注了数据与算法之美在这篇文章中&#xff0c;我将总结新老Python程序员常犯的一些错误&#xff0c;以帮助你们在自己的工作避免犯同样或类似错误。推荐阅读《Python3.0科学计算指南》首先我要说明一下的是&#xff0c;这些都是来源于第一手的经验。我以…

米兰大学计算机科学,米兰大学

很多去意大利留学的学生会选择去米兰大学留学&#xff0c;那么留学米兰大学需要了解哪些重要事项呢&#xff1f;跟着出国留学网来看看吧!欢迎阅读。意大利留学米兰大学解析院校基本信息欧洲排名7所在省州伦巴第大区所在城市Milano学校性质公立建校年代1923年学校人数60406人官方…

650c公路车推荐_2020最具性价比的中高端公路整车盘点

当你从小白成为进阶玩家后&#xff0c;发现陪伴自己多年公路车逐渐不能满足自己需求时&#xff0c;你渐渐将目光转向高端公路车&#xff0c;当你被“坑蒙拐骗”试骑了顶级公路车后&#xff0c;换车的想法在脑中油然而生。然而理想很丰满&#xff0c;现实很骨感。干瘪腰包把你从…