Рекомендую прочитать мое async
вступление .
В итоге все async
методы начинают выполняться синхронно. Поэтому, когда AsynchronousProcessing
вызывает GetInfoAsync
, GetInfoAsync
начинает работать синхронно, как и любой другой метод. Метод async
может стать асинхронным, если есть await
. В этом случае GetInfoAsync
вызывает Task.Delay
(опять же, синхронно, как обычный вызов метода), а затем передает Task
в await
. На этом этапе await
изучит задачу; если он уже завершен, он продолжит работать синхронно; в противном случае он будет работать асинхронно и вернет незавершенную задачу из GetInfoAsync
.
Выполняются задачи, возвращенные методами async
. Я обычно не использую термин «выполняется», потому что они на самом деле не запускают код на процессоре и потому что статус задачи на самом деле не Running
. Это состояние "асинхронного выполнения", к сожалению, называется WaitingForActivation
(хотя оно ничего не ждет).
Так как, если он не запустится сразу, я ожидаю, что GetInfoAsync сделает что-то вроде return new Task (() => ...);
Ключевое слово async
управляет созданием задачи. Как отмечено выше, задачи являются «горячими» или «в процессе». Это не то же самое, что «запуск» или «запуск», оба из которых подразумевают задачи, выполняющие код процессора. Существует два типа задач: задачи, которые я называю делегатом, и задачи обещания . Те, которые возвращены из async
методов, являются Обещанием.
Если новых потоков с await нет, то как они будут работать параллельно?
Они запускаются одновременно (не в параллельно , поскольку на задержке не заблокирован дополнительный поток).
Однако, когда await Task.Delay(..)
завершится, возможно, будет использован другой поток. await
возобновит в своем захваченном контексте и выполнит return "hi";
в этом контексте. Если захваченный контекст является контекстом пула потоков, то эта одна строка кода будет выполняться в потоке пула потоков. Конечный автомат async
преобразует return
в код, который завершает задачу, ранее возвращенную этим методом async
.