В последние несколько дней я тестировал новые возможности .net 4.5 и c # 5.
Мне нравятся его новые функции async / await. Ранее я использовал BackgroundWorker для обработки более длинных процессов в фоновом режиме с отзывчивым пользовательским интерфейсом.
Мой вопрос: после этих замечательных новых функций, когда я должен использовать async / await и когда BackgroundWorker ? Каковы общие сценарии для обоих?
Ответы:
async / await предназначен для замены таких конструкций, как
BackgroundWorker
. Хотя вы, безусловно, можете использовать его, если хотите, у вас должна быть возможность использовать async / await, наряду с несколькими другими инструментами TPL, для обработки всего, что там есть.Поскольку оба работают, все сводится к личным предпочтениям относительно того, когда вы используете. Что для тебя быстрее ? Что тебе легче понять?
источник
async
/await
также позволяет асинхронное программирование без потоков пула потоков.Это, вероятно, TL; DR для многих, но, я думаю, сравнивать
await
с ними всеBackgroundWorker
равно, что сравнивать яблоки и апельсины, и мои мысли по этому поводу следующие:BackgroundWorker
предназначен для моделирования одной задачи, которую вы хотите выполнить в фоновом режиме, в потоке пула потоков.async
/await
- это синтаксис для асинхронного ожидания в асинхронных операциях. Эти операции могут использовать или не использовать поток пула потоков или даже использовать любой другой поток . Итак, они яблоки и апельсины.Например, вы можете сделать что-то вроде следующего с
await
:Но вы, вероятно, никогда не смоделируете это в фоновом режиме, скорее всего, вы сделаете что-то подобное в .NET 4.0 (до
await
):Обратите внимание на несоответствие удаления по сравнению между двумя синтаксисами и то, как вы не можете использовать
using
безasync
/await
.Но вы бы не сделали что-то подобное с
BackgroundWorker
.BackgroundWorker
обычно предназначен для моделирования одной длительной операции, которая не должна влиять на скорость отклика пользовательского интерфейса. Например:Там действительно нет ничего, что вы можете использовать async / await,
BackgroundWorker
создает поток для вас.Теперь вы можете использовать вместо TPL:
В этом случае
TaskScheduler
для вас создается поток (предполагается по умолчаниюTaskScheduler
), который можно использоватьawait
следующим образом:На мой взгляд, главное сравнение заключается в том, сообщаете ли вы о прогрессе или нет. Например, у вас может быть
BackgroundWorker like
это:Но вы бы не справились с этим, потому что перетаскиваете компонент фонового рабочего на поверхность проектирования формы - то, что вы не можете сделать с
async
/await
иTask
... т.е. вы выиграли » t создать объект вручную, установить свойства и установить обработчики событий. Вы бы заполнить только в телеDoWork
,RunWorkerCompleted
иProgressChanged
обработчики событий.Если бы вы «преобразовали» это в async / await, вы бы сделали что-то вроде:
Без возможности перетаскивания компонента на поверхность конструктора читатель сам решит, что лучше. Но это, для меня, сравнение между,
await
аBackgroundWorker
не то, можете ли вы ждать встроенные методы, какStream.ReadAsync
. Например, если вы используетеBackgroundWorker
по назначению, может быть трудно конвертировать в использованиеawait
.Другие мысли: http://jeremybytes.blogspot.ca/2012/05/backgroundworker-component-im-not-dead.html
источник
var t1 = webReq.GetResponseAsync(); var t2 = webReq2.GetResponseAsync(); await t1; await t2;
. Который будет ждать две параллельные операции. Ожидать намного лучше для асинхронных, но последовательных задач, ИМО ...await Task.WhenAny(t1, t2)
что-нибудь, когда любая из задач будет выполнена первой. Вы, вероятно, захотите цикл, чтобы убедиться, что другая задача завершена тоже. Обычно вы хотите знать, когда конкретная задача завершается, что приводит вас к написанию последовательныхawait
s.Это хорошее введение: http://msdn.microsoft.com/en-us/library/hh191443.aspx Раздел Threads - это то, что вы ищете:
источник
BackgroundWorker явно помечен как устаревший в .NET 4.5:
Статья MSDN "Асинхронное программирование с использованием Async и Await (C # и Visual Basic)" рассказывает:
ОБНОВИТЬ
«для операций, связанных с вводом-выводом, потому что код проще и вам не нужно защищаться от условий гонки» Какие условия гонки могут возникнуть, не могли бы вы привести пример? "
Этот вопрос нужно было поставить отдельным постом.
В Википедии есть хорошее объяснение условий гонок . Необходимая часть этого - многопоточность и из той же статьи MSDN Асинхронное программирование с Async и Await (C # и Visual Basic) :
То есть «ключевые слова async и await не вызывают создание дополнительных потоков».
Насколько я могу вспомнить свои собственные попытки, когда я изучал эту статью год назад, если вы запускали и играли с примером кода из той же статьи, вы можете столкнуться с ситуацией, когда это не асинхронные версии (вы можете попытаться преобразовать это для себя) блокировать на неопределенный срок!
Также по конкретным примерам можно поискать на этом сайте. Вот несколько примеров:
источник