I have a timer that needs to not process its elapsed event handler at the same time. But processing one Elapsed event may interfere with others. I implemented the below solution, but something feels wrong; it seems like either I should be using the timer differently or using another object within the threading space. The timer seemed to fit best because I do need to periodically check for a status, but sometimes checking will take longer than my interval. Is this the best way to approach this?
// member variable
private static readonly object timerLock = new object();
private bool found = false;
// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();
public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
lock(timerLock)
{
if (!found)
{
found = LookForItWhichMightTakeALongTime();
}
}
}
I use the System.Threading.Timer like so
or
and
or
If
LookForItWhichMightTakeALongTime()
is going to take a long time, I would suggest not using aSystem.Windows.Forms.Timer
because doing so will lock up your UI thread and the user may kill your application thinking that it has frozen.What you could use is a
BackgroundWorker
(along with aTimer
if so desired).And you can call
RunWorkerAsync()
from anywhere you want to, even from aTimer
if you want. And just make sure to check if theBackgroundWorker
is running already since callingRunWorkerAsync()
when it's running will throw an exception.I usually stop the timer while processing it, enter a try/finally block, and resume the timer when done.
You could set AutoReset to false, then explicitly reset the timer after you are done handling it. Of course, how you handle it really depends on how you expect the timer to operate. Doing it this way would allow your timer to drift away from the actual specified interval (as would stopping and restarting). Your mechanism would allow each interval to fire and be handled but it may result in a backlog of unhandled events that are handled now where near the expiration of the timer that cause the handler to be invoked.