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()
之前开始?
答案 0 :(得分:1)
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
,最终将其存储在{{3 }}。然后在m_continuationObject
中调用它。