详解.NET 异步编程,如何透过现象,看async/await本质
Posted DotNET技术圈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解.NET 异步编程,如何透过现象,看async/await本质相关的知识,希望对你有一定的参考价值。
前言
博客园中有很多关于 .NET async
/await
的介绍,但是很遗憾,很少有正确的,甚至说大多都是“从现象编原理”都不过分。
最典型的比如通过前后线程 ID 来推断其工作方式、在 async
方法中用 Thread.Sleep
来解释 Task
机制而导出多线程模型的结论、在 Task.Run
中包含 IO bound 任务来推出这是开了一个多线程在执行任务的结论等等。
看上去似乎可以解释的通,可是很遗憾,无论是从原理还是结论上看都是错误的。
要了解 .NET 中的 async
/await
机制,首先需要有操作系统原理的基础,否则的话是很难理解清楚的,如果没有这些基础而试图向他人解释,大多也只是基于现象得到的错误猜想。
初看异步
说到异步大家应该都很熟悉了,2012 年 C# 5 引入了新的异步机制:Task
,并且还有两个新的关键字 await
和 async
,这已经不是什么新鲜事了,而且如今这个异步机制已经被各大语言借鉴,如 javascript、TypeScript、Rust、C++ 等等。
下面给出一个简单的对照:
语言 | 调度单位 | 关键字/方法 |
---|---|---|
C# | Task<> 、ValueTask<> |
async 、await |
C++ | std::future<> |
co_await |
Rust | std::future::Future<> |
.await |
JavaScript、TypeScript | Promise<> |
async 、await |
当然,这里这并不是本文的重点,只是提一下,方便大家在有其他语言经验的情况下(如果有),可以认识到 C# 中 Task
和 async
/await
究竟是一个和什么可以相提并论的东西。
多线程编程
在该异步编程模型诞生之前,多线程编程模型是很多人所熟知的。一般来说,开发者会使用 Thread
、std::thread
之类的东西作为线程的调度单位来进行多线程开发,每一个这样的结构表示一个对等线程,线程之间采用互斥或者信号量等方式进行同步。
多线程对于科学计算速度提升等方面效果显著,但是对于 IO 负荷的任务,例如从读取文件或者 TCP 流,大多数方案只是分配一个线程进行读取,读取过程中阻塞该线程:
Copy以上是关于详解.NET 异步编程,如何透过现象,看async/await本质的主要内容,如果未能解决你的问题,请参考以下文章
如何正确理解.NET 4.5和C#5.0中的async/await异步编程模式