Зачем использовать Async/Await Over Normal Threading или Tasks?
Я много читал о async и жду, и поначалу я этого не понимал, потому что я не правильно понимал потоки или задачи. Но после того, как я попытаюсь разобраться с обоими, мне интересно: зачем использовать async/await
, если вам удобно с потоками?
Асинхронность async/await может быть выполнена с помощью сигнализации потока, или Thread.Join()
и т.д. Это просто для экономии времени и "меньше" проблем?
Ответы
Ответ 1
Да, это синтаксический сахар, который упрощает работу с потоками, а также упрощает управление кодом, поскольку управление потоками выполняется во время выполнения. await
немедленно отпустите поток и разрешите этому потоку или другому выбрать, где он остановился, даже если он сделан в основном потоке.
Как и другие абстракции, если вы хотите полностью контролировать механизмы под обложками, тогда вы по-прежнему свободны реализовать подобную логику с помощью сигнализации потока и т.д.
Если вам интересно узнать, что создает async/await
, вы можете использовать Reflector или ILSpy для декомпилирования сгенерированного кода.
Прочитайте Что делает async и ждет генерировать? для описания того, что С# 5.0 делает от вашего имени.
Ответ 2
Если ожидание было просто вызовом Task.Wait
, для этого нам не нужен специальный синтаксис и новые API. Основное отличие состоит в том, что async/await
полностью освобождает текущий поток во время ожидания завершения. Во время асинхронного ввода-вывода вообще нет нити. IO - это небольшая структура данных внутри ядра.
async/await
использует обратный вызов под капотом и делает всю свою гадость (подумайте о обратных вызовах JavaScript...), идите в путь.
Обратите внимание, что async не просто перемещает работу в фоновый поток (в общем). Он освобождает все задействованные темы.
Ответ 3
Сравнение async
и await
с потоками похоже на сравнение яблок и трубных гаечных ключей. С 10 000 футов они могут выглядеть схожими, но они очень разные решения самых разных проблем.
async
и await
- все о асинхронном программировании; в частности, позволяя способу приостановить себя, пока он ожидает некоторую операцию. Когда метод приостанавливается, он возвращается к вызывающему абоненту (обычно возвращает задачу, которая завершается, когда метод завершается).
Я предполагаю, что вы знакомы с потоками, которые связаны с управлением потоками. Ближайшая параллель с потоком в мире async
Task.Run
, который начинает выполнять некоторый код в фоновом потоке и возвращает задачу, которая завершается, когда этот код завершается.
async
и await
были тщательно разработаны, чтобы быть агрегированными по потоку. Таким образом, они отлично работают в потоке пользовательского интерфейса приложений WPF/Win8/WinForms/Silverlight/WP, сохраняя поток пользовательского интерфейса, не связывая ресурсы пула потоков. Они также хорошо работают в многопоточных сценариях, таких как ASP.NET.
Если вы ищете хороший ввод в async
/await
, я написал один в своем блоге, в котором есть ссылки на дополнительное рекомендуемое чтение.
Ответ 4
Существует разница между функциями Threads и async/await.
Подумайте о ситуации, когда вы вызываете сеть, чтобы получить некоторые данные из сети. Здесь поток, который вызывает сетевой драйвер (вероятно, работает в каком-то svchost процессе), блокируется и потребляет ресурсы.
В случае Async/await, если вызов не связан с сетью, он переносит весь вызов на обратный вызов, используя SynchronizationContext, который способен получать обратный вызов из внешнего процесса. Это освобождает Thread, и Thread будет доступен для других вещей, чтобы потреблять.
Асинхронность и Concurrency - две разные вещи, первая - просто вызов чего-то в асинхронном режиме, в то время как более поздняя - действительно привязана к процессору. Темы, как правило, лучше, если вам нужно concurrency.
Я написал блог давно, описывая эти функции.
С# 5.0 vNext - новый асинхронный шаблон
Ответ 5
async/await
не использует потоки; что одно из больших преимуществ. Он позволяет реагировать на ваше приложение без дополнительной сложности и накладных расходов, присущих потокам.
Цель состоит в том, чтобы упростить работу приложения при работе с длительными операциями ввода-вывода. Например, это здорово, если вам нужно загрузить кучу данных с веб-сайта или прочитать файлы с диска. В этих случаях перекручивание новой нити (или потоков) является излишним.
Общее правило - использовать потоки через Task.Run
при работе с операциями, связанными с ЦП, и async/await
при работе с связанными с I/O операциями.
У Stephen Toub есть отличный пост в блоге на async/await
, который я рекомендую вам прочитать.