技术交流 > 心得分享 > 浅谈 C# Task和async/await

浅谈 C# Task和async/await

1.基于任务的异步模式

Task-based Asynchronous Pattern(TAP)是.NET4.0推出的一种新的异步编程模式,TAP的特色就是使用单独的方法来初始化和实现异步,使得异步编程的代码很简洁。在System.Threading.Tasks 命名空间里,提供了名为 Task 的类,每一个 Task 代表一个异步操作。以下为三种方法创建并异步执行Task:

image.png


2.async/await语法糖

.NET4.5推出了新的异步编程模式:async/await,提供了一种更为简洁的方法实现异步,async 用于修饰一个方法,标识它可以被异步执行。一般情况下,一个异步方法的返回值类型应该为 Task 或者 Task<T>,在UI事件中可以为 void,而 await 则用于等待某个异步方法执行完毕并获取返回值。

异步方法的返回值有以下三种:

① Task<T>:如果调用方法想通过调用异步方法获取一个T类型的返回值,那么签名必须为Task<T>;

② Task:如果调用方法不想通过异步方法获取一个值,仅仅想追踪异步方法的执行状态,那么我们可以设置异步方法签名的返回值为Task;

③ void:如果调用方法仅仅只是调用一下异步方法,不和异步方法做其他交互,我们可以设置异步方法签名的返回值为void,这种形式也叫做“调用并忘记”。

image.png

任何使用了 async 修饰的方法,都一定存在至少一个 await,任何异步方法的名称都推荐以 Async 结尾,async和await的搭配形成了嵌套。当遇到await关键字时,会立即返回一个 Task,将执行权转交给当前异步方法的调用方,从而让程序等待的同时可以执行其他代码。在程序进行I/O处理,或者UI事件响应时,使用async/await是十分高效率的。


3.async/await ≠ 多线程

我们可以看到Task执行的时候是使用了ThreadPool的空闲线程的,而async/await则有一些不同。我们需要先了解一下异步操作的两种类别:

①I/O关联的异步操作(IO-bound Operation):在硬件(如硬盘、网卡)进行,不需要线程,也不占用CPU,如读取网络资源或文件

②CPU关联的异步操作(CPU-bound Operation):需要大量使用CPU,需要其他线程,如长时间的计算

由于读取网络资源或者读取文件的操作可以由特定的硬件完成,而不依赖CPU,所以 .NET 通过向操作系统发送对应的请求,由系统通知硬件进行处理,在请求的同时,.NET 向操作系统写入了一个回调函数(委托),在硬件处理完任务并通知操作系统时,操作系统会执行这个回调函数,这个函数会改变 Task的状态。在需要大量执行 I/O 操作时,await/async 有着巨大的优势,特别是网络服务器接受大量需要进行IO的请求时,await/async 能在IO时释放线程,让服务器有限的线程得以接受更多的网络请求,而不是造成阻塞,这有利于增加服务器的吞吐量。


4.小结

.net中异步的发展过程可以大致概括为:Thread --> ThreadPool --> Task --> async/await,

各自的特点:

ThreadPool:减少Thread创建数量和管理Thread的成本

Task:改进ThreadPool中执行顺序、任务延续、任务取消的问题

async/await:处理本地I/O和网络I/O任务,提高任务执行效率


2022-07-01 13:27:15
评论
  • 评论加载中...

评论内容: