Почему "флаг" bool генерируется для конечного автомата async/await?

Если вы компилируете следующий код:

private async Task<int> M()
{
    return await Task.FromResult(0);
}

А затем декомпилировать его (я использовал dotPeek) и изучить все важные MoveNext метод, вы увидите bool переменная объявлена ​​в начале; dotPeek выбрал "флаг" для меня.

bool flag = true;

В этом случае вы увидите одного последующего потребителя этой переменной в операторе case по умолчанию после инициирования первого асинхронного вызова:

if (!awaiter.IsCompleted)
{
    this.\u003C\u003E1__state = 0;
    this.\u003C\u003Eu__\u0024awaiter11 = awaiter;
    this.\u003C\u003Et__builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, Program.\u003CP\u003Ed__10>(ref awaiter, ref this);
    flag = false;
    return;
}

Я пробовал полдюжины более сложных примеров, чем мой первоначальный, и они согласуются только с присвоением этой переменной перед выходом из метода. Другими словами, во всех случаях, которые я до сих пор пробовал, эта переменная не только никогда не используется, но и получает только не начальное значение непосредственно перед возвратом из метода - момент времени, когда назначение определенно бесполезный.

В качестве фона я наслаждаюсь процессом попытки реализовать async/await в Javascript через кросс-компилятор C# -> JS. Я пытаюсь понять, в какой ситуации мне нужно рассмотреть полезность этого флага. На первый взгляд это кажется ложным, и поэтому я должен игнорировать это. Однако я хотел бы понять, почему компилятор C# вводит эту переменную - я подозреваю, что есть более сложные выражения, которые используют эту переменную полезным способом.

Чтобы выразить это кратко: почему компилятор C# генерирует это flag переменная?

1 ответ

Решение

Следующий комментарий, размещенный под вопросом, описывает его использование:

Оберните ваш оператор await в блок try-finally и установите некоторую переменную внутри блока finally. Я не совсем понимаю, что делает логика IL, но я только что сделал быстрый просмотр, и похоже, что он использует эту переменную флага, чтобы проверить, когда выполнять код внутри блока finally.

–Илиан Пинзон

Также Стивен Клири добавляет некоторую полезную информацию для заинтересованного читателя. Он рекомендует эту серию блогов и, в частности, этот пост.

@IlianPinzon имеет правильный ответ. Это объяснено более подробно в одном из сообщений eduasync Джона Скита. Поскольку вы пишете кросс-компилятор, я настоятельно рекомендую прочитать всю эту серию.

–Стефен Клири

Другие вопросы по тегам