【发布时间】:2021-05-26 19:26:23
【问题描述】:
当我们将方法标记为 async 并在 Compiler 中使用 await 时,会将 async 函数转换为状态机 例如,
private static async Task<String> MyMethodAsync(Int32 argument) { ... }
变身
[DebuggerStepThrough, AsyncStateMachine(typeof(StateMachine))]
private static Task<String> MyMethodAsync(Int32 argument) {
StateMachine stateMachine = new StateMachine() {
m_builder = AsyncTaskMethodBuilder<String>.Create(),
m_state = -1, // Initialize state machine location
m_argument = argument // Copy arguments to state machine fields
};
// Start executing the state machine
stateMachine.m_builder.Start(ref stateMachine);
return stateMachine.m_builder.Task; // Return state machine's Task
}
而AsyncTaskMethodBuilder的定义是
public struct AsyncTaskMethodBuilder<TResult> {
private Task<TResult> m_task;
...
public void SetResult(TResult result) {
... // call Task's TrySetResult method
}
}
据我所知,TaskCompletionSource 用于创建不执行代码的任务对象,这是状态机中的完美案例,因为它创建了一个虚拟任务 (stateMachine.m_builder.Task) 重新调整给调用者,并且一旦工作线程完成原始任务后,状态机会通过其m_builder成员调用SetResult手动将结果添加到虚拟任务中,那么为什么AsyncTaskMethodBuilder不使用TaskCompletionSource呢?
【问题讨论】:
-
鉴于
TaskCompletionSource是使用Task实现的,我想这是为了避免在实现中使用额外的类。但只有实施者才能真正回答这个问题。 -
如果您查看
AsyncTaskMethodBuilder的源代码,您会看到很多关于性能调整的评论。与使用通用类型相比,使用可以精确调整到编译器需求的专用类型可能是更好的选择。