为什么延续在GetResult()之前开始?

问题描述 投票:0回答:1
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()。

最后一个代码。

延续结束。

Question

我真的不明白为什么Continuation begins.来到GetResult().之前。在我的直觉中,GetResult()应该是第一位的。

为什么继续在GetResult()之前开始?

c# async-await
1个回答
1
投票

continuation是在等待的东西完成时执行的委托。通常情况下,等待的TaskAwaiter会将continuation存储在一个字段中,并在Task完成时运行它。

编译器生成的状态机使用它来进入下一个状态,然后在正在等待的东西上调用.GetResult()(两者都得到结果,并抛出任何异常);

所以continuation是一个代表,最终调用GetResult()

你可以找到OnCompleted被称为here的地方。 continuationAsyncMethodBuilderCore.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中调用它。

© www.soinside.com 2019 - 2024. All rights reserved.