2013-10-01 4 views
2

Я разрабатываю приложение Windows Forms, которое вызывает службу WCF по истечении заданного интервала и показывает вывод в соответствии с данными, полученными от службы. У меня был план использовать таймер для этой цели, который вызывает этот метод службы WCF через 500 мс. Но некоторые из моих коллег сказали мне использовать фона рабочего, а затем на Work_Completed событие повторного запуска рабочего. Я хочу знать, в чем разница между этими двумя? Создает ли таймер фоновый поток? Какой из них лучше всего подходит для длительных задач?Timer vs. reetitive background worker

+0

Какой таймер? Есть несколько. Некоторые используют потоки, а некоторые нет. – Ralf

ответ

4

A Timer почти наверняка более подходит с точки зрения потребления ресурсов. A BackgroundWorker собирается создать новый поток только для этой задачи. Создание нового потока - довольно дорогостоящая операция.Хотя существует множество различных реализаций таймера, и их реализация будет отличаться, они, как правило, будут полагаться на инструменты ОС, которые будут периодически запускать событие, что будет предпочтительнее запуска нового выделенного потока.

Основные отличия в объектах Timer - это то, что они делают, когда они «готовы». Некоторые создают новый поток пула потоков; некоторые из них имеют выделенный поток, который совместно используется всеми экземплярами таймера для запуска обработчика (-ов), некоторые маршалируют код в поток пользовательского интерфейса (или какой-то другой контекст синхронизации), и это последнее, что вы, вероятно, захотите. Если вы используете таймер, который доступен в определенной структуре пользовательского интерфейса, который вы используете, это поведение, которое вы увидите.

6

From MSDN website: -

BackgroundWorker создает поток на ThreadPool (через асинхронный делегат Invoke). Таймеры BCL используют либо поток ThreadPool для , либо могут в некоторых случаях поднять события tick/elapsed/etc в потоке пользовательского интерфейса (в случае таймера WinForms или Timers.Timer с ISynchronizeInvoke поставляемый ему).

BackgroundWorker предоставляет оптимальный API для фоновых потоков в среде . Он позволяет использовать метод на фоновом потоке (через событие DoWork) и предоставляет простой способ получить уведомление о прогрессе и завершении в потоке пользовательского интерфейса (ProgressChanged и RunWorkerCOmpleted events), не беспокоясь о каком-либо cross -простой вызов.

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

Threading.Timer - это своего рода таймер «уродливого API». Timers.Timer просто обертывает Threading.Timer в более удобный API и предоставляет способ автоматически вызывать прошедшее событие в потоке пользовательского интерфейса (через свойство SynchronizingObject). Если вы установите свойство SynchronizingObject , код не выполняется в фоновом потоке, он сразу получает , связанный с потоком пользовательского интерфейса.

В общем, внутри пользовательского интерфейса BackgroundWorker проще использовать , чем другие.

+0

Значит, это означает, что на более глубоком уровне системы стандартный таймер является всего лишь рекурсивной функцией? –

+1

@AishwaryaShiva Нет. Что заставляет вас так говорить? – Servy

+0

@Servy, как я только что прочитал выше, говорит, что таймер выполняется в потоке пользовательского интерфейса, поэтому, насколько мне известно, он должен быть рекурсивной функцией. Потому что это часть потока пользовательского интерфейса (UI-класс) и он замораживает пользовательский интерфейс, когда он выполняется. Я просто не спрашиваю об этом. На самом деле, я хочу знать, что такое таймер на самом деле на более глубоком уровне? Я видел объяснения MSDN, но они предназначены только для целей разработки. Я действительно хочу это знать для своих собственных знаний и исследований. –

3

Стандарт System.Windows.Forms.Timer должен быть в порядке. Он вызывает обратный вызов в потоке пользовательского интерфейса, что означает, что во время обработки внутри обратного вызова это потенциально заморозит вашу реакцию на интерфейс. Но это только проблема, если вы много работаете внутри обратного вызова или блокируете поток.

Чтобы избежать блокировки потока, просто выполните асинхронный вызов WCF.

A BackgroundWorker не имеет смысла для того, что вы хотите сделать. Все, что вы хотите сделать, это подождать 500 мс, прежде чем выполнять какой-либо код, поэтому просто используйте System.Windows.Forms.Timer.

4

По моему опыту, основное преимущество Background Worker состоит в том, что события ProgressChanged и RunWorkerCompleted будут выполняться в той же теме, в которой был создан экземпляр рабочего. Итак, если вы запустили фонового рабочего в потоке пользовательского интерфейса, событие RunWorkerCompleted также будет запускаться в потоке пользовательского интерфейса. Это делает так, что вам не нужно беспокоиться о том, чтобы делать незаконные вызовы с перекрестными потоками, если вы хотите обновить компоненты своего пользовательского интерфейса при завершении фоновой работы.

+0

Существуют (серверные) 'Timer' классы, которые вы можете использовать, которые также будут отмечены в потоке пользовательского интерфейса; вам не нужен BGW, чтобы получить это поведение. – Servy

+0

Я думал, что единственным, который по умолчанию отмечен в потоке пользовательского интерфейса, был System.Windows.Forms.Timer. Здесь есть хорошая статья, сравнивающая таймеры здесь: http://msdn.microsoft.com/en-us/magazine/cc164015.aspx – Keith

+0

«System.Timers.Timer» может быть настроен для запуска в потоке пользовательского интерфейса, и вам нужно рассмотреть все таймеры, специфичные для каждой парадигмы пользовательского интерфейса. Есть таймер форм и таймер WPF (DispaterTimer) и т. Д. – Servy