Является ли async и await исключительно асинхронным программированием на основе графического интерфейса?

Я читал о новых операторах async и await в C# и пытался выяснить, в каких обстоятельствах они могли бы мне пригодиться. Я изучил несколько статей MSDN и вот что прочитал между строк:

Вы можете использовать async для обработчиков событий Windows Forms и WPF, чтобы они могли выполнять длительные задачи, не блокируя поток пользовательского интерфейса, пока выполняется основная часть операции.

async void button1_Click(object sender, EventArgs e)
{
    // even though this call takes a while, the UI thread will not block
    // while it is executing, therefore allowing further event handlers to
    // be invoked.
    await SomeLengthyOperationAsync();
}

Метод, использующий await, должен быть async, а это означает, что использование любой функции async где-то в вашем коде в конечном итоге приводит к тому, что все методы в последовательности вызовов от обработчиков событий пользовательского интерфейса вплоть до метода async самого нижнего уровня также будут async.

Другими словами, если вы создаете поток с обычной старой доброй точкой входа ThreadStart (или консольным приложением со старой доброй точкой входа static int Main(string[] args)), то вы не можете использовать async и await, потому что в какой-то момент вам пришлось бы использовать await, и сделать метод который использует его async, и, следовательно, в вызывающем методе вы также должны использовать await и сделать этот async и так далее. Но как только вы достигаете точки входа в поток (или Main()), нет вызывающей стороны, которой await передал бы управление.

Таким образом, вы не можете использовать async и await без графического интерфейса, который использует стандартный цикл сообщений WinForms и WPF. Я предполагаю, что все это действительно имеет смысл, поскольку MSDN утверждает, что программирование async не означает многопоточность, а вместо этого использует свободное время потока пользовательского интерфейса; при использовании консольного приложения или потока с определяемой пользователем точкой входа многопоточность будет необходима для выполнения асинхронных операций (если не используется совместимый цикл обработки сообщений).

У меня вопрос, верны ли эти предположения?


person dialer    schedule 29.09.2012    source источник
comment
+1 за хороший вопрос, даже если он полностью неверно истолковал документацию :)   -  person Jon Skeet    schedule 29.09.2012
comment
См. несколько примеров без графического интерфейса здесь   -  person Zaid Masud    schedule 29.09.2012


Ответы (4)


Таким образом, вы не можете использовать async и await без графического интерфейса, который использует стандартный цикл сообщений WinForms и WPF.

Это абсолютно не дело.

В Windows Forms и WPF async/await имеет удобное свойство возвращаться в поток пользовательского интерфейса после завершения ожидаемой асинхронной операции, но это не означает, что это единственная цель.

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

Например, предположим, что у вас есть веб-служба с высоким трафиком, которая в основном передает запросы другим веб-службам. Он тратит большую часть своего времени на ожидание других вещей, будь то из-за сетевого трафика или реального времени в другой службе (например, в базе данных). Для этого вам не нужно много потоков, но с блокирующими вызовами вы, естественно, получаете поток для каждого запроса. С async/await у вас будет очень мало потоков, потому что очень немногим запросам действительно потребуется какая-либо работа, выполняемая для них в любой момент времени, даже если запросов было много " в полете».

Проблема в том, что async/await проще всего продемонстрировать с кодом пользовательского интерфейса, потому что каждый знает, как тяжело либо правильно использовать фоновые потоки, либо выполнять слишком много работы в потоке пользовательского интерфейса. Это не означает, что это единственное место, где эта функция полезна — далеко не так.

Различные серверные технологии (например, MVC и WCF) уже поддерживают асинхронные методы, и я ожидаю, что другие последуют их примеру.

person Jon Skeet    schedule 29.09.2012
comment
Теперь, когда я прочитал все ответы, я думаю, что знаю, где я ошибся. Я правильно понял, что это обычное программирование на основе обратного вызова, но с улучшенным кодом. Я предположил, что магия await использует что-то строго связанное с графическим интерфейсом, чтобы знать, где вызывать обратный вызов (то есть оставшуюся часть метода после await), когда вместо этого она использует SynchronizationContext.Current, TaskScheduler.Current и все, что ОС считает подходящим, например. ThreadPool с приоритетом именно в этом порядке. К сожалению, я такой человек, которому неудобно использовать то, что я не мог запрограммировать сам. - person dialer; 30.09.2012
comment
@dialer: Нет ничего плохого в желании заглянуть за магию. Вам может понравиться моя серия блогов Eduasync: msmvps.com/blogs/jon_skeet/ архив/теги/Eduasync/default.aspx - person Jon Skeet; 30.09.2012
comment
Обновлена ​​ссылка для начала серии Eduasync (другая ссылка у меня не работала): blogs.msmvps.com/jonskeet/2011/05/08/ - person David Dowdle; 28.08.2015

Метод, использующий await, должен быть асинхронным, а это означает, что использование любой асинхронной функции где-то в вашем коде в конечном итоге приводит к тому, что все методы в последовательности вызовов от обработчиков событий пользовательского интерфейса вплоть до асинхронного метода самого низкого уровня также становятся асинхронными.

Неправда — методы, помеченные как асинхронные, просто означают, что они могут использовать ожидание, но у вызывающих эти методы нет ограничений. Если метод возвращает Task или Task<T>, они могут использовать ContinueWith или что-то еще, что вы могли бы сделать с задачами в 4.0.

Хорошим примером без пользовательского интерфейса является MVC4 AsyncController.

В конечном счете, async/await в основном заключается в том, чтобы переписать компилятор, чтобы вы могли написать код, который выглядит как синхронный, и избежать всех обратных вызовов, которые вы должны были делать до того, как был добавлен async/await. Это также помогает с обработкой SynchronizationContext, полезной для сценариев со сходством потоков (фреймворки пользовательского интерфейса, ASP.NET), но даже без них это все еще полезно. Например, main всегда может сделать DoStuffAsync().Wait();. :)

person James Manning    schedule 29.09.2012

У меня вопрос, верны ли эти предположения?

No.

Вы можете использовать асинхронность для обработчиков событий Windows Forms и WPF, чтобы они могли выполнять длительные задачи, не блокируя поток пользовательского интерфейса, пока выполняется основная часть операции.

Истинный. Также верно для других приложений пользовательского интерфейса, включая Silverlight и Windows Store.

И также справедливо для ASP.NET. В данном случае поток HTTP-запрос не блокируется.

Метод, использующий await, должен быть асинхронным, а это означает, что использование любой асинхронной функции где-то в вашем коде в конечном итоге приводит к тому, что все методы в последовательности вызовов от обработчиков событий пользовательского интерфейса вплоть до асинхронного метода самого низкого уровня также становятся асинхронными.

Это лучшая практика ("async до конца"), но это не обязательно. Вы можете заблокировать результат асинхронной операции; многие люди предпочитают делать это в консольных приложениях.

обычная старая добрая точка входа ThreadStart

Что ж... Я должен не согласиться с "обычным старым добрым". Как я объясняю в своем блоге, Thread в значительной степени худший вариант для выполнения фоновых операций.

Я рекомендую вам просмотреть мое введение в async и await и следовать ознакомьтесь с async / await часто задаваемыми вопросами.

person Stephen Cleary    schedule 29.09.2012

  1. async-await — это всего лишь оболочка для манипуляций с классом Task, которая является частью так называемой параллельной библиотеки задач — TPL (опубликованной до технологии автоматической генерации кода async-await).
  2. Итак, вы не можете использовать какие-либо ссылки на элементы управления пользовательского интерфейса в асинхронном режиме ожидания.
  3. Как правило, async-await является мощным инструментом для любых отношений между сетью и сервером, загрузки ресурсов, sql. Он работает с интеллектуальными данными ожидания с живым пользовательским интерфейсом.
  4. Типичное приложение TPL: от простого цикла большого размера до многоэтапных параллельных вычислений в сложных вычислениях на основе общих данных (ContinueWith и т. д.)
person Sergey Orlov    schedule 02.11.2015