c# - 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() 方法,并在任务完成后“返回”。
调用线程如何知道如何在某个时候“回来”?内部发生了什么来实现这一点?
解决方案
当方法包含await
时,编译器会创建所谓的异步状态机。正在编辑的任务被await
存储起来,之后的所有内容都await
被标记为任务的继续。
通过状态机AsyncTaskMethodBuilder<>
a 和 a TaskAwaiter<>
,基础设施跟踪执行和同步上下文,捕获局部变量并最终在等待完成时跟踪原始状态。Task
它通过循环(调用内部MoveNext
方法)直到任务完成、被取消或出错(由于异常)来做到这一点。假设是前者,然后在适当的上下文中调用延续。当抛出异常时,AggregateException
您通常会得到Task
“解包”(抛出第一个异常)以模仿正常同步方法的体验。
这是一个整体的简化。有各种优化和一堆机制可以使这一切正常工作。对于一个关于这个主题的好博客,我推荐这个关于异步方法的微软系列。
推荐阅读
- excel - 列出外部链接并允许用户输入所需的单元格位置 - 此代码有什么问题?
- uml - 从类图中生成代码:两个类之间的组合不会改变生成的 Java 代码中的任何内容
- express - NuxtJS Express SocketIO JWT - 服务器完全加载后发出停止
- javascript - 布尔柯里化 Javascript
- firebase - Firebase 数据库提供不一致的数据
- c# - 带有tryparse的Do-while循环不会进入else语句
- cookies - 如何通过 HTTP 使用 Set-Cookie 跨站点?
- sql - 将 Access PIVOT 查询转换为 SQL Server
- c - 文件导入时的 C 内存问题
- amazon-web-services - 如何通过 terraform 将 alb 注册为目标组的目标