System.Timers.Timer / Threading.Timer против потока с whileLoop + Thread.Sleep для периодических задач - PullRequest
44 голосов
/ 13 мая 2010

В моем заявлении я должен периодически отправлять сердцебиение приложению «брата».

Лучше ли это сделать с помощью System.Timers.Timer / Threading.Timer или использования потока с циклом while и Thread.Sleep?

Интервал сердцебиения составляет 1 секунду.

while(!exit)
{
   //do work
   Thread.Sleep(1000);
}

или

myTimer.Start( () => { 
                       //do work 
                      }, 1000); //pseudo code (not actual syntax)...

Ответы [ 4 ]

32 голосов
/ 13 мая 2010

System.Threading.Timer имеет мой голос.

System.Timers.Timer предназначен для использования в функциях таймера на основе сервера (ваш код выполняется как сервер / служба на хост-компьютере, а не запускается пользователем).

Поток с циклом while и командой Thread.Sleep - действительно плохая идея, учитывая существование более надежных механизмов таймера в .NET.

23 голосов
/ 13 мая 2010

Таймеры сервера - это существа, отличные от спящих потоков.

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

Таймеры, с другой стороны, могут генерировать свои события в любом потоке, что позволяет улучшить возможности планирования. Однако стоимость использования таймеров немного сложнее в вашем коде - и тот факт, что вы не сможете контролировать, какой поток запускает логику, по которой запускается событие таймера. Из документов:

Серверный таймер предназначен для использовать с рабочими потоками в многопоточная среда. сервер таймеры могут перемещаться между потоками в обрабатывать поднятое событие Elapsed, что приводит к большей точности, чем Windows таймеры при поднятии события на время.

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

Не путайте Таймеры сервера с " Таймеры Windows ". Последнее обычно ссылается на сообщения WM_TIMER, которые могут быть доставлены окну, что позволяет приложению планировать и отвечать на обработку по времени в своем основном потоке без сна. Однако Windows Timers также может ссылаться на Win API для низкоуровневой синхронизации (что не совпадает с WM_TIMER).

21 голосов
/ 13 мая 2010

Ни то, ни другое:)

Сон, как правило, осуждается (к сожалению, я не могу вспомнить подробности, но, с одной стороны, это беспрерывный «блок»), и Timer с большим количеством багажа. Если возможно, я бы порекомендовал System.Threading.AutoResetEvent как таковой

// initially set to a "non-signaled" state, ie will block
// if inspected
private readonly AutoResetEvent _isStopping = new AutoResetEvent (false);

public void Process()
{
    TimeSpan waitInterval = TimeSpan.FromMilliseconds (1000);

    // will block for 'waitInterval', unless another thread,
    // say a thread requesting termination, wakes you up. if
    // no one signals you, WaitOne returns false, otherwise
    // if someone signals WaitOne returns true
    for (; !_isStopping.WaitOne (waitInterval); )
    {
        // do your thang!
    }
}

Использование AutoResetEvent (или его двоюродного брата ManualResetEvent) гарантирует истинный блок с поточно-ориентированной сигнализацией (для таких вещей, как изящное завершение выше). В худшем случае это лучшая альтернатива Sleep

Надеюсь, это поможет:)

1 голос
/ 13 мая 2010

Я обнаружил, что единственная реализация таймера, которая на самом деле масштабируется, это System.Threading.Timer. Все остальные реализации кажутся довольно поддельными, если вы имеете дело с нетривиальным числом запланированных элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...