There is absolutely no reason you can't have multiple timers. I have programs that have hundreds of timers, and at any time a handful of them can be actually doing work. The point of timers is that they allow you to schedule periodic actions and not consume any CPU resources except when the actions are actually being processed. That is, if you set a timer to tick once per minute, then that timer doesn't occupy a thread, doesn't consume any memory (beyond a token amount for the timer handle and the callback address), and doesn't consume any CPU resources. Only when the timer "ticks" once per minute is a thread allocated to execute code for it. And typically that is a pool thread that already exists, so thread startup time is negligible.
Using a timer is very easy: you create a method for the timer to execute, and you schedule the timer to run it. For example:
System.Threading.Timer myTimer =
new System.Threading.Timer(MyTimerProc, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
void MyTimerProc(object state)
{
// do something here
}
You could have another timer that ticks every 30 seconds and executes a different timer proc:
System.Threading.Timer myOtherTimer =
new System.Threading.Timer(MyOtherTimerProc, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
void MyOtherTimerProc(object state)
{
// do something else here
}
The timers won't interfere with each other. Of course, if code in the timer procs modifies shared data (for example, both procs try to update a list or a dictionary), then you'll have to synchronize access to that shared data or use a concurrent data structure.
You can get into trouble with reentrancy if the processing in your timer proc takes longer than the timer period. If the processing in MyTimerProc
takes longer than 60 seconds, then another timer tick can come along and now you have two threads executing that timer proc. That can cause many different types of problems if your code is not set up to handle it. Typically you eliminate that problem by making the timer a one-shot and restarting it at the end of each processing cycle. There are examples of doing that here on Stack Overflow.
System.Timers.Timer
is a component wrapper around System.Threading.Timer
. The idea that it's "optimized for high performance threading" or some such is silly. System.Timers.Timer
gives you a familiar event-oriented interface, and also provides a SynchronizingObject
, which lets you have the event raised on a particular thread rather than having to explicitly Invoke
as you would with System.Threading.Timer
. Typically, that's only useful in UI applications.
System.Timers.Timer
has one particularly ugly "feature" that I consider a bug: it squashes exceptions. As the documentation says:
In the .NET Framework version 2.0 and earlier, the Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event.
That behavior still exists in .NET 4.5. The problem is that if you have your Elapsed
event:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff here
}
If your event handler throws an exception, it will propagate back to the timer code, which squashes the exception and never tells you about it. In effect, the timer does this:
try
{
OnTimedEvent(source, args);
}
catch
{
// Squash those pesky exceptions. Who needs them?
}
It's a bug hider because you never know that the exception was thrown. So your program doesn't work and you can't figure out why. It's for this reason that I strongly recommend that you NOT use System.Timers.Timer
. Use System.Threading.Timer
instead; after all, it's the base that System.Timers.Timer
is built on.