I have code that looks like this
mTestModeMetadataTimer = new System.Threading.Timer(SomeTimerCallback, null, 1000, Timeout.Infinite);
Stopwatch tmStopwatch = new Stopwatch();
private void SomeTimerCallback(object state)
{
// doing minimal work here
Console.WriteLine("{0}: SomeTimerCallback time: {1}", System.Threading.Thread.CurrentThread.ManagedThreadId, tmStopwatch.ElapsedMilliseconds);
tmStopwatch.Restart();
// Better to be on the safe side and do this slightly more than once per second, than slightly less.
mTestModeMetadataTimer.Change(990, Timeout.Infinite);
}
Everything works fine except that occasionally there's a huge delay between timer events as seen in this console output.
31: SomeTimerCallback time: 998
21: SomeTimerCallback time: 997
20: SomeTimerCallback time: 999
3: SomeTimerCallback time: 989
3: SomeTimerCallback time: 1000
3: SomeTimerCallback time: 994
37: SomeTimerCallback time: 999
3: SomeTimerCallback time: 991
29: SomeTimerCallback time: 1002
37: SomeTimerCallback time: 1000
3: SomeTimerCallback time: 17568
3: SomeTimerCallback time: 999
29: SomeTimerCallback time: 993
This is a small portion of a pretty sizable application. The same behavior existed with a System.Timers.Timer and, in fact, occurs for various other times throughout the application. I added the thread ID to the console output of this particular timer to hopefully gain a little more insight as to why there's a random 17.5 second elapsed time among the correct one second events.
Is there something I'm obviously doing wrong? Perhaps there's some more data I can gather to figure out why my timers are acting funny?
Any suggestions here would be greatly appreciated.
From your comment the reason this happens is you are exhausting the threads in the thread pool. Because every thread was in use the timer had to wait 17.5 seconds for a thread to become available before it could run.
Your options as I see it are either increase the max number of threads in the thread pool or use a different timer that does not use the thread pool (
(Still uses the thread pool to kick it off) or aSystem.Timers.Timer
with a synchronization object that does not use the thread poolSystem.Windows.Forms.Timer
with a message pump running)