async/await基于编译器生成的状态机实现,每次await暂停会保存执行状态,恢复时从中断点继续;其核心是编译器将异步方法转换为实现IAsyncStateMachine的结构体,通过MoveNext()驱动流程。await操作依赖awaiter对象的IsCompleted、OnCompleted和GetResult三个成员,判断是否同步完成或注册回调以异步恢复。执行上下文由SynchronizationContext或TaskScheduler决定,UI线程中会自动捕获上下文确保回到原线程,而ConfigureAwait(false)可禁用此行为以提升性能并避免死锁。async/await不创建新线程,挂起期间线程返回线程池,恢复时由调度器安排续体执行,利用底层I/O或任务调度实现并发,无栈撕裂与线程阻塞,高效支持异步编程。

当你写 async Task<int> GetDataAsync(),C# 编译器不会生成普通方法,而是将其重写为一个**状态机结构体(struct)**,实现 IAsyncStateMachine 接口。这个结构体包含:字段(保存局部变量、参数、awaitable 对象)、MoveNext() 方法(核心执行逻辑)、State 字段(记录当前执行到哪一步)。每次 await 暂停时,不是线程被阻塞,而是状态机被“冻结”并保存现场;恢复时,从上次 State 值继续执行 MoveNext()。
await 后的对象必须实现 GetAwaiter() 方法,返回一个具备以下成员的 awaiter:
常见 awaitable 类型如 Task、Task<T>、ValueTask、自定义 awaiter 都遵循该模式。编译器在 await 处插入逻辑:检查 IsCompleted → 若否,调用 OnCompleted 注册续体(continuation),然后 return;若是,跳过挂起直接执行后续代码。
await 恢复执行的位置,不取决于“谁调用了它”,而取决于当前捕获的 SynchronizationContext 或 TaskScheduler:
可用 ConfigureAwait(false) 显式禁用上下文捕获,提升性能并避免死锁(尤其在库代码中强烈推荐)。
async/await 不创建新线程,也不强制线程切换。真正的并发来自底层 I/O(如 FileStream.ReadAsync)或任务调度(如 Task.Run)。await 挂起后,线程通常回归线程池处理其他请求;恢复时,由调度器将续体排入目标上下文(如 UI 消息队列)或线程池队列。整个过程无栈撕裂、无线程阻塞——这是它高效的关键。
基本上就这些。理解状态机构造、awaiter 协议和上下文流转,就能看透 async/await 的行为边界与性能特征。
以上就是C# async/await的底层原理是什么 - 深入解析状态机与线程上下文的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号