Почему продолжение начинается до GetResult ()? - PullRequest
0 голосов
/ 23 апреля 2019
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()?

1 Ответ

1 голос
/ 23 апреля 2019

continuation - делегат, который выполняется, когда ожидаемая вещь завершается.Обычно ожидаемый TaskAwaiter хранит continuation в поле и запускает его после завершения Task.

Конечный автомат, сгенерированный компилятором, использует это для перехода к следующему состоянию, котороев свою очередь вызовет .GetResult() для ожидаемой вещи (как для получения результата, так и для выдачи любых исключений);

Так что continuation - это делегат, который в конечном итоге вызывает GetResult().

Вы можете найти, где OnCompleted называется , здесь .continuation является результатом AsyncMethodBuilderCore.GetCompletionAction, который создает его из MoveNextRunner.Run, который вызывает MoveNext на конечном компьютере .

Если вы посмотрите код, генерируемый компилятором для вашего асинхронного метода , вы увидите, что MoveNext вызывает awaiter.GetResult().

Чтобы увидеть, как Task работает здесь, начните с TaskAwaiter.OnCompleted и увидите, что он вызывает Task.SetContinuationForAwait, что вызывает AddTaskContinuation, что в итоге сохраняет его вm_continuationObject.Затем вызывается в Task.FinishContinuations.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...