До Async & Await было два типа методов. Те, кто возвращал результат напрямую, и те, кто получил функцию обратного вызова в качестве параметра. В последнем случае метод вызывался в том же потоке синхронно и не возвращал значения, а позже в том же или другом потоке ваша функция обратного вызова была бы вызвана с результатом. Исторически все операции ввода-вывода (диск, сеть, даже память) работали с обратными вызовами (фактически - с прерываниями), но языки среднего и высокого уровня, такие как C #, маскировали бы все это внутренне, поэтому конечным пользователям не нужно изучать / писать код низкого уровня.
До определенного момента это работало довольно хорошо, за исключением того, что эта оптимизация тратила некоторые физические ресурсы. Например, Node.js превзошел некоторые другие языковые / серверные платформы по своему ограничению, что вынуждает разработчиков использовать модель обратного вызова вместо «управляемого» режима.
Это подтолкнуло C # и другие языки к возврату к модели обратного вызова, но читаемость кода действительно пострадала (spaguetti обратного вызова кода). Так были введены Async и Await.
Асинхронизация и ожидание позволят вам написать в «модели обратного вызова» с «управляемым» синтаксисом. Все обратные вызовы обрабатываются компилятором.
Каждый раз, когда вы пишете 'await' в асинхронном методе, ваш метод фактически разделяется на два метода, связанных обратным вызовом.
Теперь вы можете написать асинхронный метод, который выполняет обычный код sync
, без ожидания, без переключения потоков или ввода / вывода. Этот «асинхронный» метод фактически будет работать синхронно. Таким образом, на самом деле это то же самое для await method1()
или вызова без await
. Зачем? потому что ваш асинхронный вызов ничего не ожидает, поэтому ваш асинхронный код по-прежнему является частью непрерывного кода.
Если внутри вашего метода вы ожидаете один, два или более различных методов, то ваш метод будет разделен на одну, две или более частей. И только первая часть будет гарантированно выполняться синхронно. Все остальные части будут выполняться в другом потоке в зависимости от кода, который вы ожидаете.
TL; DR;
Асинхронный / ожидающий метод не гарантирует многопоточность или параллельную обработку. Это будет зависеть от полезной нагрузки (вызываемый асинхронный метод). Например, загрузка http, как правило, будет парализована, если вы управляете ожиданиями, потому что это функции, которые в основном являются официантами внешнего ответа. С другой стороны, интенсивная обработка ЦП, такая как сжатие файла, потребует другой формы управления процессором / потоком, не предоставляемой async / await.
Если вы не ожидаете асинхронный метод, ваш код обязательно будет работать синхронно до первого ожидания вызываемого метода, если он есть. Но позже он может запустить синхронизацию или нет.