Собираю их в произвольном порядке:
BackgroundWorker (# 5)
Мне нравится использовать BackgroundWorker, когда я делаю что-то спользовательский интерфейс.Его преимущество заключается в том, что события потока и завершения запускаются в потоке пользовательского интерфейса, что означает, что вы не получите неприятных исключений при попытке изменить элементы пользовательского интерфейса.У этого также есть хороший встроенный способ сообщить о прогрессе.Одним из недостатков этого режима является то, что если в вашей работе блокируются вызовы (например, веб-запросы), у вас будет поток, который бездействует, ничего не делая во время работы.Это, вероятно, не проблема, если вы думаете, что у вас их будет всего несколько.
IAsyncResult / Begin / End (APM, # 4)
Это широко распространенная и мощная, но сложная в использовании модель.Обработка ошибок является проблематичной, поскольку вам необходимо повторно перехватывать исключения в вызове End, а неперехваченные исключения не обязательно возвращают его в какие-либо соответствующие фрагменты кода, которые могут его обработать.Это может привести к постоянному зависанию запросов в ASP.NET или просто к тому, что ошибки загадочно исчезают в других приложениях.Вы также должны быть бдительными в отношении свойства CompletedSynchronously
.Если вы не отследите и не сообщите об этом должным образом, программа может зависнуть и пропустить ресурсы.С другой стороны, если вы работаете в контексте другого APM, вы должны убедиться, что все асинхронные методы, которые вы вызываете, также сообщают об этом значении.Это означает выполнение другого вызова APM или использование Task
и приведение его к IAsyncResult
для получения его свойства CompletedSynchronously
.
В сигнатурах также много накладных расходов: вы должны поддерживатьПроизвольный объект для прохождения, создайте собственную реализацию IAsyncResult, если вы пишете асинхронный метод, который поддерживает опросы и дескрипторы ожидания (даже если вы используете только обратный вызов).Кстати, вы должны использовать только обратный вызов здесь.Когда вы используете дескриптор ожидания или опрос IsCompleted
, вы теряете поток, пока выполняется операция.
Асинхронный шаблон на основе событий (EAP)
Тот, которого не было в вашем списке, но я упомяну для полноты картины.Это немного дружелюбнее, чем APM.Вместо обратных вызовов есть события, и на сигнатурах методов висит меньше мусора.Обработка ошибок немного проще, поскольку она сохраняется и доступна в обратном вызове, а не повторно генерируется.CompletedSynchronously также не является частью API.
Задачи (# 1)
Задачи - это еще один дружественный асинхронный API.Обработка ошибок проста: исключение всегда существует для проверки обратного вызова, и никто не заботится о CompletedSynchronously.Вы можете создавать зависимости, и это отличный способ справиться с выполнением нескольких асинхронных задач.Вы даже можете обернуть в них асинхронные методы APM или EAP (один из которых вы пропустили).Еще одна хорошая вещь об использовании задач - ваш код не заботится о том, как реализована операция.Он может блокироваться в потоке или быть полностью асинхронным, но потребляющий код не заботится об этом.Вы также можете легко смешивать операции APM и EAP с Задачами.
Parallel.For методы (# 3)
Это дополнительные помощники поверх Задач.Они могут выполнить часть работы, чтобы создать задачи для вас и сделать ваш код более читабельным, если ваши асинхронные задачи подходят для выполнения в цикле.
ThreadPool.QueueUserWorkItem (# 2)
Это утилита низкого уровня, которая на самом деле используется ASP.NET для всех запросов.Он не имеет встроенной обработки ошибок, такой как задачи, поэтому вам нужно все перехватить и передать обратно в ваше приложение, если вы хотите узнать об этом.Он подходит для работы с интенсивным использованием процессора, но вы не хотите делать какие-либо блокирующие вызовы, такие как синхронный веб-запрос.Это потому, что пока он работает, он использует поток.
async
/ await
Ключевые слова
Новое в .NET 4.5, эти ключевые слова позволяют писать асинхронный код без явных обратных вызовов.Вы можете ожидать на Task
, и любой код ниже этого будет ожидать завершения этой асинхронной операции без использования потока.