首页 > 解决方案 > C# async/await - 程序如何跟踪调用“await”的位置?

问题描述

await正在运行的线程遇到 an 时,内部使用什么机制来“标记”该特定方法最终需要在等待的任务完成后恢复?考虑以下方法:

public async void DoSomething()
{
   await Task.Run(() => SomeLongRunningWork());
   // Code to resume when the task is done...
   Console.WriteLine("Resuming...");
}

当达到上述await条件时,线程池上的一个线程用于执行长时间运行的工作。此外,调用线程会立即退出 DoSomething() 方法,并在任务完成后“返回”。

调用线程如何知道如何在某个时候“回来”?内部发生了什么来实现这一点?

标签: c#multithreadingasynchronousasync-awaittask

解决方案


当方法包含await时,编译器会创建所谓的异步状态机。正在编辑的任务被await存储起来,之后的所有内容都await被标记为任务的继续。

通过状态机AsyncTaskMethodBuilder<>a 和 a TaskAwaiter<>,基础设施跟踪执行和同步上下文,捕获局部变量并最终在等待完成时跟踪原始状态。Task它通过循环(调用内部MoveNext方法)直到任务完成、被取消或出错(由于异常)来做到这一点。假设是前者,然后在适当的上下文中调用延续。当抛出异常时,AggregateException您通常会得到Task“解包”(抛出第一个异常)以模仿正常同步方法的体验。

这是一个整体的简化。有各种优化和一堆机制可以使这一切正常工作。对于一个关于这个主题的好博客,我推荐这个关于异步方法的微软系列。


推荐阅读