День двести шестнадцатый. #ЗаметкиНаПолях

Многопоточность.

9. Async/await. Продолжение

Асинхронный поток выполнения

Когда поток выполнения достигает выражения await, есть два варианта:

1. Ожидаемая асинхронная операция уже завершена.

В этом случае процесс продолжается, как обычно. Если операция завершилась неудачно и захватила исключение, генерируется исключение. В противном случае возвращается результат (например, извлекается string из Task<string>), и вы переходите к следующей строке программы. Все это делается без какого-либо переключения контекста потока или создания продолжений.

2. Ожидаемая асинхронная операция ещё не завершена.

В этом случае метод асинхронно ожидает завершения операции, а затем продолжает работу в соответствующем контексте. Это асинхронное ожидание означает, что метод не выполняется дальше. К асинхронной операции прикрепляется продолжение, содержащее остаток кода асинхронного метода, а сам метод возвращается. Инфраструктура гарантирует, что продолжение выполняется в нужном потоке: обычно это либо поток из пула (где не имеет значения, какой поток используется), либо поток пользовательского интерфейса. С точки зрения разработчика, можно представить, что метод приостанавливается до тех пор, пока асинхронная операция не завершится. Компилятор гарантирует, что все локальные переменные, используемые в методе, будут иметь те же значения, как это происходит с блоками итераторов при yield return.



Возврат или завершение

Для асинхронных методов есть разница между возвратом из метода и завершением метода. Возврат из асинхронного метода может производиться несколько раз, когда у метода больше нет работы, которую он может сделать на данный момент. А завершиться метод может только один раз.



Замечание: до первого выражения await, метод выполняется полностью синхронно. Вызов асинхронного метода не похож на запуск новой задачи в отдельном потоке, и вы должны убедиться, что всегда пишете асинхронные методы так, чтобы они быстро возвращались. Конечно, это зависит от контекста, в котором вы пишете код, но, как правило, следует избегать выполнения длительной работы в асинхронном методе. Выделите её в другой метод, для которого создайте отдельную задачу.



Продолжение следует…



Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.