class MyAwaitable
{
public MyAwaiter GetAwaiter()
{
return new MyAwaiter();
}
public class MyAwaiter : INotifyCompletion
{
public bool IsCompleted { get; }
public void GetResult()
{
Console.WriteLine("GetResult().");
}
public void OnCompleted(Action continuation)
{
Console.WriteLine("Continuation begins.");
continuation();
Console.WriteLine("Continuation ends.");
}
}
}
class Program
{
static async Task Main()
{
await new MyAwaitable();
Console.WriteLine("The last code.");
}
}
输出:
继续开始。
调用getResult()。
最后一个代码。
延续结束。
我真的不明白为什么Continuation begins.
来到GetResult().
之前。在我的直觉中,GetResult()
应该是第一位的。
为什么继续在GetResult()
之前开始?
continuation
是在等待的东西完成时执行的委托。通常情况下,等待的TaskAwaiter
会将continuation
存储在一个字段中,并在Task
完成时运行它。
编译器生成的状态机使用它来进入下一个状态,然后在正在等待的东西上调用.GetResult()
(两者都得到结果,并抛出任何异常);
所以continuation
是一个代表,最终调用GetResult()
。
你可以找到OnCompleted
被称为here的地方。 continuation
是AsyncMethodBuilderCore.GetCompletionAction
的结果,它是从MoveNextRunner.Run
创造的,calls MoveNext
on the state machine。
如果你看看compiler-generated code for your async method,你可以看到MoveNext
称为awaiter.GetResult()
。
要了解Task
如何在这里工作,请从TaskAwaiter.OnCompleted
开始,并看到它调用Task.SetContinuationForAwait
,它调用AddTaskContinuation
,最终将其存储在m_continuationObject
中。然后在Task.FinishContinuations
中调用它。