Task和TaskAwaitor功能分析 - 指南
一、Task 的原理和机制
1️⃣ 定义与角色
Task是System.Threading.Tasks.Task类,用于表示一个异步操作的 状态和结果。核心作用:
- 状态管理:Pending、Running、RanToCompletion、Faulted、Canceled。
- 结果存储:
Task<T>保存异步操作的返回值。 - 异常传播:未捕获的异常封装在 Task 中。
- 挂起/恢复 continuation:当 Task 完成时,执行注册的 continuation。
可以理解为:Task = 异步操作的“承诺”和“容器”。
2️⃣ 内部结构(简化)
一个 Task 主要有:
Task
├─ m_stateFlags // 状态标记:Pending / Completed / Faulted / Canceled
├─ m_result // Task 的结果
├─ m_continuationObject // 注册的 continuation delegate(可能是列表)
├─ m_exception // 捕获的异常
├─ m_parent // 父 Task,用于 Task 层级
├─ m_cancellationToken // 可取消
- m_continuationObject 是核心,它存储 async/await 注册的 continuation。
- Task 完成后会遍历 continuation list,并由调度器(ThreadPool/SynchronizationContext)执行。
3️⃣ Task 执行流程
场景 A:CPU-bound (Task.Run)
- Task 被创建并排队到 ThreadPool。
- ThreadPool worker 执行委托。
- Task 内部状态更新为 RanToCompletion 或 Faulted。
- 调用
InvokeContinuations()→ 执行所有注册的 continuation。
场景 B:I/O-bound (ReadAsync)
- Task 由
TaskCompletionSource或 I/O wrapper 创建。 - I/O 提交到内核(IOCP)。
- Task 完成 (
SetResult) → 调度 continuation。
二、TaskAwaiter 的原理和机制
1️⃣ 定义与角色
TaskAwaiter 是
System.Runtime.CompilerServices.TaskAwaiter结构体。角色:
- 桥梁:连接 Task 与 async/await 状态机。
- 注册 continuation:决定 Task 未完成时如何挂起状态机。
- 获取结果:Task 已完成时,通过
GetResult()返回值或抛出异常。
简单理解:TaskAwaiter = Task ↔ AsyncStateMachine 的桥梁。
2️⃣ TaskAwaiter 内部机制
struct TaskAwaiter
{
Task m_task;
bool IsCompleted => m_task.IsCompleted;
void OnCompleted(Action continuation)
=> m_task.OnCompleted(continuation);
void GetResult()
=> throw m_task.Exception if faulted, else return result;
}
- IsCompleted:检查 Task 是否完成。
- OnCompleted:注册 continuation。
- GetResult:获取 Task 结果(同步执行),或者抛出异常。
⚠️ TaskAwaiter 本身不创建线程,不执行异步操作,只是桥梁。
三、Task + TaskAwaiter 的交互流程
以 await someTask 为例:
User Thread:
var awaiter = someTask.GetAwaiter();
if (!awaiter.IsCompleted)
awaiter.OnCompleted(MoveNext); // 捕获 continuation 和 ExecutionContext
Task 未完成:
Task 完成后:
Task 内部遍历 continuation list
如果捕获 SynchronizationContext → Post
否则 → ThreadPool.QueueUserWorkItem
ExecutionContext.Run(capturedContext, MoveNext)
Continuation Thread:
MoveNext() 执行 async 方法剩余代码
四、线程与上下文调度
| 阶段 | 执行线程 | 说明 |
|---|---|---|
| TaskAwaiter.GetAwaiter / OnCompleted | 调用 await 的线程 | 仅注册 continuation |
| Task 完成时遍历 continuation | Task 完成线程(IOCP Poller / ThreadPool worker) | 调度到目标线程 |
| continuation 执行 (MoveNext) | ThreadPool / SynchronizationContext | ExecutionContext 已恢复,执行 async 代码 |
| Task 已完成同步场景 | 调用线程 | GetResult() 直接返回结果 |
核心理解:TaskAwaiter 本身不执行异步操作,Task 本身也不直接选择线程。真正执行 async 方法剩余逻辑的是被调度到的线程。
五、执行总结
Task = 异步操作状态 + 结果 + continuation 容器。
TaskAwaiter = Task ↔ async 状态机桥梁。
Task 完成后 continuation 的执行:
- Task 内部负责触发。
- 线程由 ThreadPool 或 SynchronizationContext 决定。
- ExecutionContext 在执行线程被恢复。
异步方法剩余代码执行由 continuation(MoveNext)在调度线程执行。
浙公网安备 33010602011771号