图解 .NET async/await

2021-05-03

我非常认同一图胜千言的说法,因此我也喜欢用图来解释各种技术概念。本文通过图解来说明 .NET 中 async/await 如何工作。



async/await 背后的主要思想是,当我们在一个正在进行的 I/O 操作上等待时,调用线程可以被释放出来做其他工作,它提供了很好的线程可重用性。因此,具备更好的可扩展性,与同步/等待方式相比,更少的线程可以处理相同数量的操作。


这里的主要作用是进行所谓的 overlapped I/O(在 Windows 环境),它允许异步地将 I/O 操作委托给操作系统,只有在操作完成后,提供的回调才通知调用者结果。这里的主要工作是 I/O 完成端口(IOCP)


I/O 完成端口是 Windows 中异步 I/O 的一种非常有效的机制,只需要一个端口就可以观察大量正在进行的操作。在 .NET 环境下,实际上只由一个 IOCP 来完成。然后,几个 I/O 完成线程(由 ThreadPool 管理)观察这个单一的 IOCP。IOCP 线程的典型数量大约等于逻辑处理器的数量,但 ThreadPool 默认设置下可以创建多达 1000 个线程(我们可以改变这个最大值)。


I/O 操作的回调是在其中一个 IOCP 线程上执行的,它设置操作的结果并决定:


  • 在 IOCP 线程上原地执行 continuation 操作,这样做有一定好处,因为它不会产生上下文切换,避免了缓存回收,但有可能出现用户代码污染 IOCP 线程(并导致线程泄漏)。

  • 或者将其调度回另一个地方,可能是由 SynchronizationContext / TaskScheduler 指定,所以典型的情况是被工作线程排队执行。


通常情况下,大多数的 continuation 都被调度给工作线程。其中一个最重要的例外是 Windows 的 HttpClient continuation(自 .NET Core 2.1 以来)。


注意:在 Linux 环境下,使用 epoll 机制代替 IOCP。通过 epoll 线程监听事件,将 continuation 安排给工作线程(不会出现内联 inlining )。并且使用 AIO 和 io_uring 重建 Linux 的 ThreadPool 工作。


所有的点都由一个状态机实例连接起来,进行状态跟踪,执行 continuation,保持上下文等。


这张图片也让我想起 Stephen Cleary 著名文章 "没有线程 (1)",他解释说,当一个异步 I/O 操作被执行时,没有 "执行用户代码" 的线程被消耗。事实上也确实如此,虽然有评论中提到,有 IOCP 线程被阻塞,用于处理 I/O 完成端口通知,但几乎可以视为没有线程。


(1) https://blog.stephencleary.com/2013/11/there-is-no-thread.html


我发表在 Twitter 上面关于 ThreadPool 和 I/O 完成端口关系的图片也引起不少讨论,有兴趣的读者可以参阅。


https://twitter.com/konradkokosa/status/1264855190131400704


英文原文:

https://tooslowexception.com/net-asyncawait-in-a-single-picture/


参考阅读:






本文由高可用架构翻译,技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。


高可用架构
改变互联网的构建方式

相关文章

.NET 调整图片尺寸(Resize)各种方法

2021-05-06
(给DotNet加星标,提升.Net技能)转自:晓晨Mastercnblogs.com/stulzq/p/14283068.html本文中如无特别说明 .NET指.NET 5或者更高...

.NET应用如何优雅的实现功能定时开关

2021-05-06
本文的内容是对前篇《.NET 应用如何优雅的做功能开关》的补充.因此请先阅读前文,了解相关库的用法....

.NET 5 中的隐藏特性,99%的人还不知道!

2021-05-06
hez2010cnblogs.com/hez2010/p/13963803.html前言双十一当天,个人觉得非常香,并且花了 10 分钟时间就把自己的 4 个 .NET Core ...

深入研究 .NET 5 的开放式遥测

2021-05-06
就明白了我的意思,这个SDK支持所有主要的编程语言,包括C#和ASP.NET Core.这篇文章中将讨论OpenTelemetry的全部含义,为...

.NET零基础逆向图文教程 2.1 再谈查壳

2021-05-06
2019 年假期,出于某些原因,我写了一套关于.NET 语言的逆向入门教程,其实就是 dnSpy 的软件食用指南,很高兴一些朋友能通过...

C#/.NET IOC框架——Unity容器基础入门

2021-05-06
NET Thread类实现线程等待,回调,多线程并发操作●ASP.NET--WebForm框架●ORM框架如何选型——各大ORM框架比较

【.NET与树莓派】上手前的一些准备工作

2021-05-05
.NET Iot 不是什么新鲜事物,百科很强大,故老周在此也不必多介绍.现在的时代和老周当年学 QBasic 的时代不同,那时候拉根电话...

.NET 6 Preview 1 开箱上手!带你尝试新版本更新!

2021-05-05
(给DotNet加星标,提升.Net技能)转自:痴者工良cnblogs.com/whuanle/p/14414465.html前言.NET 6 Preview 1 发布了,.NET统一是...

「译」 .NET 5 新增的Http, Sockets, DNS 和 TLS 遥测

2021-05-05
.NET 一直在稳定的增加和改善对应用程序进行跨平台的诊断分析,在.NET Core 3.0, 我们看到了 EventCounters[1] 的介绍,用于观察...

.NET内存包装类 Memory 和 Span 相关类型

2021-05-05
NET Core 支持以下两种所有权模型:支持单个所有权的模型缓冲区在其整个生存期内拥有单个所有者.支持所有权转让的模型缓冲区...

随机推荐

就18%的人睡眠无障碍,用手机软件测睡眠质量靠谱吗?

2021-04-15
这个软件靠谱吗?一个测试为了验证效果,我们的实验员将软件设置成了四十分钟的午睡模式,然后把手机放在枕头边,但是实验员并...

百度App Objective-C/Swift 组件化混编之路(一)

2020-12-18
完成基础架构后,克里斯带领开发小组陆续完成语法设计、编译器... Objective-C 来 wrap 一遍,运行效率更高,维护成本更低.得益于 ...

Zephyr网络管理模块分析-Event机制

2020-11-27
_NET_ETHERNET_CODE等Command 表示模组功能下不同的request和event,例如WIFI下有1234567891011121314enum net_...

大前端完整学习路线(详解)

2020-07-09
Web开发工作流:GIT/SVN、Yeoman脚手架、NPM/Bower依赖管理工具、Grunt/Gulp/Webpack. ● MVC/MVVM/MVW框架:Angular....

最让程序员感到崩溃的10种编程语言

2020-05-02
Visual Basic 语言介绍:这种语言和相应的开发环境通常是用来开发Windows应用程序(图...Perl 语言介绍:Perl是一种高级的,用途广泛的解释型语言...Java 语言介绍:Java起初是一种被用在交互电视上的语言...

App环境分离的实现:Android篇

2019-07-18
我在App架构经验总结中有简单提到环境分离的实现方案,但没有深入讲实现细节.本系列则打算用两篇文章分别详细讲讲Android和...

开发者现在可以下载 Android SDK 5.0 了!

2019-04-19
来下载 Android SDK,并使用 Android Studio 开发你的应用:Android 5.0 SDK Platform & ToolsAndroid 5.0 Emulator System Image ...

四川农业大学教务网系统登录入口http://jiaowu.sicau.edu.cn

2018-12-16
小编整理分享四川农业大学教务处系统入口http://jiaowu.sicau.edu.cn/ 机构设置教务处是全校本科教育教学管理工作的职能部门,主要...

健身达人:200斤程序员减脂半年,逆袭成肌肉男,减脂技巧很重要

2018-01-16
怀特是一位31岁的程序员.他在学生时代一直保持规律的训练,身材也非常的不错.但是工作之后,由于训练停止和饮食不控制,导致...

Java里的for (;;)与while (true),比比看

2017-03-20
至于Java里的for(;;)与while(true),哪个更快?这种规范没有规定的问题,答案都是“看实现”,毕竟实现只要保证语义符合规范...