Как async/await разворачивается в state machine
Проследите, как компилятор преобразует async-метод: вызовы MoveNext, остановка на await, планирование continuation и завершение Task.
Текущий этап Готово
Исходный async-метод
Код, который пишет разработчик.
async Task<string> LoadProfileAsync()
{
Log("start");
var user = await GetUserAsync();
var score = await GetScoreAsync(user);
return $"{user}: {score}";
} State machine от компилятора
Структура переживает остановки и хранит локальные переменные в полях.
var machine = new <LoadProfileAsync>d__0();
machine.MoveNext();
state = 0; builder.AwaitUnsafeOnCompleted(...);
awaiter.GetResult(); state = -1;
state = 1; builder.AwaitUnsafeOnCompleted(...);
state = -2; builder.SetResult(result); Выполнение в Runtime
Пока идёт I/O, поток освобождён — прогресс хранит state machine.
1Вызывающий код
2MoveNext()
3I/O пользователя
4Очередь continuation
5I/O рейтинга
6SetResult()
Метод ещё не вызван: state machine и Task пока не существуют.