Await
- await 的作用是,将其修饰的表达式后面的流程作为回调加给 task;
- 注册完这个回调,线程就不必再持有当前方法了,因为后面的流程最终将会以回调的方式执行,所以相当于此方法“已经完成”了; > 划线部分应该不是很准确,涉及到一些我暂不清楚的细节
- 有的描述中会说 “方法会从 await ‘暂停’ 的地方继续执行”,这实际上是因为
await后的代码作为回调被执行了,与 “暂停” 这个概念没有关系; - “暂停” 这个概念的产生或许是因为调试的时候,看起来
await前后还是在同一个方法里,但前后的流程可能并没有在相同线程中执行(当然也有可能在相同线程中,取决于任务调度); - 如果直接调用一个
Task而不await,那么它会在线程池线程上执行,但是无法正常捕获异常;
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/await
public class AwaitOperator
{
public static async Task Main()
{
Task<int> downloading = DownloadDocsMainPageAsync();
Console.WriteLine($"{nameof(Main)}: Launched downloading.");
int bytesLoaded = await downloading;
Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
}
private static async Task<int> DownloadDocsMainPageAsync()
{
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");
var client = new HttpClient();
byte[] content = await client.GetByteArrayAsync("https://learn.microsoft.com/en-us/");
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
return content.Length;
}
}
// Output similar to:
// DownloadDocsMainPageAsync: About to start downloading.
// Main: Launched downloading.
// DownloadDocsMainPageAsync: Finished downloading.
// Main: Downloaded 27700 bytes.
- Task 完成后会通知(实际是以回调的形式执行 await 后的操作)
看 evaluation 的部分 没看懂
https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/ - 如果下一步的开始依赖于上一步的结果,那么异步甚至比同步更慢,因为还额外有线程调度的时间; - 如果几个任务之间是独立的,那么异步执行能够显著提高效率; - 通过分离 Task 的执行和 await 来实现独立任务之间的同时在不同线程上的执行; - 当使用 await 被应用到 task 上时,失败的 task 会抛出异常; - Task.Exception 属性是 System.AggregateException 类型的对象,因为异步任务执行的过程中可能会抛出多个异常; - 如果 Task.Exception 是空的,那么会创建一个 AggregateException 异常,并抛出这集合中的第一个异常; - async/await 在语义上与 ContinueWith 类似,但实际上编译器并没有将 await 表达式直接转换成 ContinueWith。编译器生成优化过的状态机代码,提供相似的运行逻辑。
Coffee cup = PourCoffee();
Console.WriteLine("Coffee is ready");
Task<Egg> eggsTask = FryEggsAsync(2);
Task<HashBrown> hashBrownTask = FryHashBrownsAsync(3);
Task<Toast> toastTask = ToastBreadAsync(2);
Toast toast = await toastTask;
ApplyButter(toast);
ApplyJam(toast);
Console.WriteLine("Toast is ready");
Juice oj = PourOJ();
Console.WriteLine("Oj is ready");
Egg eggs = await eggsTask;
Console.WriteLine("Eggs are ready");
HashBrown hashBrown = await hashBrownTask;
Console.WriteLine("Hash browns are ready");
Console.WriteLine("Breakfast is ready!");