views:

1016

answers:

4

In my application I have to send periodic heartbeats to a "brother" application.

Is this better accomplished with System.Timers.Timer/Threading.Timer or Using a Thread with a while loop and a Thread.Sleep?

The heartbeat interval is 1 second.

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

or

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

System.Threading.Timer has my vote.

System.Timers.Timer is meant for use in server-based (your code is running as a server/service on a host machine rather than being run by a user) timer functionality.

A Thread with a While loop and Thread.Sleep command is truly a bad idea given the existance of more robust Timer mecahnisms in .NET.

Justin Niessner
and you have mine.
Alan
@Alan: and you have mine
abatishchev
The System.Timers.Timer class really can be used in a user mode application just as easily as System.Threading.Timer. Internally, System.Timers.Timer uses System.Threading.Timer for it's internal timing mechanism, and only wraps it up to handle design time issues...
Reed Copsey
+6  A: 

Server Timers are a different creature than sleeping threads.

For one thing, based on the priority of your thread, and what else is running, your sleeping thread may or may not be awoken and scheduled to run at the interval you ask. If the interval is long enough, and the precision of scheduling doesn't really matter, Thread.Sleep() is a reasonable choice.

Timers, on the other hand, can raise their events on any thread, allowing for better scheduling capabilities. The cost of using timers, however, is a little bit more complexity in your code - and the fact that you may not be able to control which thread runs the logic that the timer event fires on. From the docs:

The server-based Timer is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event, resulting in more accuracy than Windows timers in raising the event on time.

Another consideration is that timers invoke their Elapsed delegate on a ThreadPool thread. Depending on how time-consuming and/or complicated your logic is, you may not want to run it on the thread pool - you may want a dedicated thread. Another factor with timers, is that if the processing takes long enough, the timer event may be raised again (concurrently) on another thread - which can be a problem if the code being run is not intended or structured for concurrency.

Don't confuse Server Timers with "Windows Timers". The later usually refers to a WM_TIMER messages tha can be delivered to a window, allowing an app to schedule and respond to timed-processing on its main thread without sleeping. However, Windows Timers can also refer to the Win API for low-level timing (which is not the same as WM_TIMER).

LBushkin
Thanks for the answer. I'm a little confused between "Server Timers" and "Windows Timers" and how that relates to System.Threading.Timer and Thread.Sleep
Alan
Okay, System.Timers.Timer is a server timer. Gotcha!
Alan
+5  A: 

Neither :)

Sleeping is typically frowned upon (unfortunately I cannot remember the particulars, but for one, it is an uninteruptible "block"), and Timers come with a lot of baggage. If possible, I would recommend System.Threading.AutoResetEvent as such

// 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!
    }
}

Using an AutoResetEvent (or its cousin ManualResetEvent) guarantees a true block with thread safe signalling (for such things as graceful termination above). At worst, it is a better alternative to Sleep

Hope this helps :)

johnny g
I like it, the ability to cleanly shutdown your thread is nice.
Scott Chamberlain
Why a for loop rather than while?
gav
@gav, `while` works just as well, `for` is a stylistic preference.
johnny g
+1  A: 

I've found that the only timer implementation that actually scales is System.Threading.Timer. All the other implementations seem pretty bogus if you're dealing with a non trivial number of scheduled items.

spender