C# 异步
C# 异步
异步和同步,可以简单理解为:
同步,即大家一起走,我系个鞋带,大家等我。
异步,则大家一起走,我系个鞋带,后面跟上。
而在某些场景下,是不能够大家一起走,而是需要大家先走,我后面跟上的。
static async Task Go () {
// ...
}
等待
有些时候,我们需要进行等待操作,比如只有一个锅做菜,那么只能等待这个锅炒完菜才能炒新的菜。
await
提供了一种非阻塞方式来启动任务。
然后该任务完成后继续执行后续任务。
// 静态 异步 返回 Task 的 Main 方法
// 如果需要使用 await 则需要增加 async 修饰符
// 并且使用 Task 代替返回的类型
static async Task Main () {
// ...
await AsyncFn(); // 等待这个操作完成
// ...
}
等待所有
可使用 WhenAll
,它返回一个 Task
,当它参数列表中的所有异步任务都完成时,返回的 Task
完成。
await Task.WhenAll(goWork, eatBreakfast, seeNew);
// 吃完早餐,看完新闻,到上班地点了,结束任务
等待任一
还有一个 WhenAny
,它同样返回一个 Task
, 但是与 WhenAll
不同,当它的参数列表中的任一异步任务完成时,通过返回的 Task
会知道该任务已完成。随后进行处理,并从参数列表中删除该任务。
var tasks = new List<Task> { goWork, eatBreakfast, seeNew };
while (tasks.Count > 0) {
Task task = await Task.WhenAny(tasks);
// todo ...
await task;
tasks.Remove(task); // 在 tasks 列表中移除 task
}
并发任务
很多情况下,需要同时进行多个操作,比如上班途中,可以边吃早餐,边看新闻等。
System.Threding.Tasks.Task
和相关类型是可用于推理正在进行任务的类。
使得可以编写更好的异步代码。
public async Task Main () {
goWork();
eatBreakfast();
seeNew();
}
异步组合
异步操作后跟随同步操作的组合也是异步操作。
即,操作任意部分为异步,则整体都是异步的。
// 异步组合
public async Task Main () {
await AsyncOperate();
SyncOperate();
SyncOperate();
}
异步异常
异步方法可以引发异常,并被捕获处理。
处理方式与同步方法一致。
try {
// async operator
}
catch (AsyncErrorType e) {
// async error handling...
}
异步场景
比如需要进行 IO 操作,使用 CPU 进行运算等。
异步编程的核心是 Task
和 Task<T>
。
它们受到 async
和 await
支持。
异步返回类型
Task
对于执行异步操作但并无返回值的方法。Task<TResult>
对于返回值的异步方法。void
对于事件处理程序。任何具有可访问的
GetAwaiter
方法的类型。该方法返回对象必须实现System.Runtime.CompilerServices.ICriticalNotifyCompletion
接口。IAsyncEnumerable<T>
对于返回异步流的方法。DispatcherOperation
适用于 Windows 的异步操作。IAsyncAction
适用于 UWP 中不返回值的异步操作。IAsyncActionWithProgress
,适用于 UWP 中只报告进程但不返回值的异步操作。IAsyncOperation
,适用于 UWP 中返回值的异步操作。IAsyncOperationWithProgress
,适用于 UWP 中既报告进程又返回值的异步操作。