У меня есть стилистический вопрос о выборе реализации фонового потока, который я должен использовать в приложении Windows Form. В настоящее время у меня есть BackgroundWorker
форма, которая имеет бесконечный (while(true))
цикл. В этом цикле я использую, WaitHandle.WaitAny
чтобы поток дремал, пока не произойдет что-то интересное. Один из дескрипторов события, на котором я жду, - это StopThread
событие " ", чтобы я мог выйти из цикла. Это событие сигнализируется когда от меня переопределяют Form.Dispose()
.
Я читал где-то, что BackgroundWorker
действительно предназначено для операций, с которыми вы не хотите связывать пользовательский интерфейс и которые имеют конечную цель - например, загрузка файла или обработка последовательности элементов. В этом случае «конец» неизвестен и только тогда, когда окно закрыто. Поэтому для меня было бы более уместным использовать фоновый поток вместо BackgroundWorker
этой цели?
источник
CancelAsync
(и проверьте, будетCancellationPending
ли ваш поток опрашиваться с короткими интервалами, если вы хотите, чтобы вместо него было возбуждено исключение, используйте a,System.Threading.Thread.Abort()
которое вызывает исключение в самом блоке потока, выберите правильную модель для ситуации.Некоторые из моих мыслей ...
источник
BackgroundWorker
предназначено для сообщения о продвижении потока заинтересованной стороне, которая обычно включает в себя пользовательский интерфейс. Документация MSDN для класса делает это совершенно ясно. Если вам просто нужно выполнить задачу в фоновом режиме, предпочтите использованиеThreadPool
потока.System.Windows.Forms
сборке;BackgroundWorker
также полезно для приложений WPF, и эти приложения могут не иметь ссылки на WinForms.Почти то, что сказал Мэтт Дэвис, со следующими дополнительными пунктами:
Для меня основным отличием
BackgroundWorker
является автоматическая сортировка завершенного события черезSynchronizationContext
. В контексте пользовательского интерфейса это означает, что завершенное событие запускается в потоке пользовательского интерфейса и может использоваться для обновления пользовательского интерфейса. Это главное отличие, если вы используетеBackgroundWorker
в контексте пользовательского интерфейса.Задачи, выполняемые с помощью оператора,
ThreadPool
не могут быть легко отменены (включаяThreadPool
.QueueUserWorkItem
И делегаты выполняются асинхронно). Поэтому, хотя это позволяет избежать накладных расходов на раскручивание потока, если вам необходимо отменить, используйтеBackgroundWorker
или или (более вероятно, за пределами пользовательского интерфейса) раскрутите поток и сохраните ссылку на него, чтобы вы могли вызвать егоAbort()
.источник
Также вы связываете поток пула для времени жизни фонового работника, что может вызывать беспокойство, поскольку их существует только конечное число. Я бы сказал, что если вы когда-либо создаете поток только один раз для своего приложения (и не используете какие-либо функции фонового рабочего), то используйте поток, а не поток backgroundworker / threadpool.
источник
Знаете, иногда проще всего работать с BackgroundWorker независимо от того, используете ли вы Windows Forms, WPF или какую-либо другую технологию. Отличная часть этих парней в том, что вы получаете многопоточность, не беспокоясь о том, где исполняется нить, что отлично подходит для простых задач.
Перед использованием сначала
BackgroundWorker
подумайте, хотите ли вы отменить поток (закрытие приложения, отмена пользователя), а затем вам нужно решить, должен ли ваш поток проверять отмены или он должен быть наложен на само выполнение.BackgroundWorker.CancelAsync()
будет установленCancellationPending
вtrue
но ничего не будет делать больше, это то ответственность нити постоянно проверять это, иметь в виду также , что вы могли бы в конечном итоге с гонки в этом подходе , где отмененного ваш пользователь, но нить завершена до тестирования наCancellationPending
,Thread.Abort()
с другой стороны, при выполнении потока будет сгенерировано исключение, которое вызывает отмену этого потока, однако вы должны быть осторожны с тем, что может быть опасно, если это исключение было внезапно вызвано в ходе выполнения.Потоки нуждаются в очень тщательном рассмотрении независимо от задачи, для дальнейшего чтения:
Параллельное программирование в .NET Framework Managed Threading Best Practices
источник
Я знал, как использовать потоки, прежде чем я знал .NET, поэтому потребовалось некоторое время, чтобы привыкнуть, когда я начал использовать
BackgroundWorker
s. Мэтт Дэвис суммировал разницу с большим превосходством, но я хотел бы добавить, что труднее точно понять, что делает код, и это может усложнить отладку. IMO проще думать о создании и закрытии потоков, чем думать о предоставлении работы пулу потоков.Я до сих пор не могу комментировать посты других людей, поэтому простите мою кратковременную хромоту, используя ответ на адрес 7
Не используйте
Thread.Abort();
вместо этого, сигнализируйте событие и придумайте, чтобы ваш поток грациозно заканчивался при сигнале.Thread.Abort()
вызываетThreadAbortException
произвольный момент выполнения потока, что может привести к несчастным случаям, таким как потерянные мониторы, поврежденное общее состояние и т. д.http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx
источник
Если это не сломано - исправьте это, пока это ... просто шутит :)
А если серьезно, то BackgroundWorker, вероятно, очень похож на то, что у вас уже есть, если бы вы начали с него с самого начала, возможно, вы бы сэкономили время - но на данный момент я не вижу в этом необходимости. Если что-то не работает, или вы думаете, что ваш текущий код трудно понять, то я бы придерживался того, что у вас есть.
источник
Основное отличие, как вы заявили, заключается в создании событий GUI из
BackgroundWorker
. Если потоку не нужно обновлять отображение или генерировать события для основного потока графического интерфейса, тогда это может быть простой поток.источник
Я хочу указать на одно поведение класса BackgroundWorker, которое еще не было упомянуто. Вы можете сделать обычный поток для запуска в фоновом режиме, установив свойство Thread.IsBackground.
Вы можете проверить это поведение, вызвав следующий метод в конструкторе окна формы.
Если для свойства IsBackground установлено значение true и вы закрываете окно, ваше приложение будет нормально завершено.
Но когда для свойства IsBackground установлено значение false (по умолчанию), и вы закрываете окно, тогда просто окно исчезнет, но процесс все равно продолжит работать.
Класс BackgroundWorker использует поток, который работает в фоновом режиме.
источник
Фоновый рабочий - это класс, который работает в отдельном потоке, но он предоставляет дополнительные функциональные возможности, которые вы не получаете с простым потоком (например, обработка отчета о ходе выполнения задачи).
Если вам не нужны дополнительные функции, предоставляемые фоновым работником - и, похоже, вам это не нужно - тогда поток будет более подходящим.
источник
Что меня удивляет, так это то, что дизайнер визуальных студий позволяет вам использовать только фоновые рисунки и таймеры, которые на самом деле не работают с сервисным проектом.
Это дает вам аккуратные элементы управления перетаскиванием на ваш сервис, но ... даже не пытайтесь развернуть его. Не сработает
Сервисы: использовать только System.Timers.Timer System.Windows.Forms.Timer не будет работать, даже если он доступен в наборе инструментов
Службы: BackgroundWorkers не будут работать, когда он работает как служба. Вместо этого используйте System.Threading.ThreadPools или вызовы Async.
источник