Reputation: 37633
I would like to clarify possible code implementaion in case if the code executing withing timerDoJob_Elapsed
is getting longer that it should.
So all internal things are gonna be coruppted/canceled and etc when timer fires next time.
Is there any pattern for this kind of problem? Any clue about make it more stable?
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
Upvotes: 0
Views: 70
Reputation: 40898
If you're using System.Timers.Timer, turn off AutoReset. Then re-enable the timer at the end of your Elapsed method.
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
mytimer.Enabled = true;
}
This way, the timer does not even start again until the task is complete. But make sure to wrap everything in your Elapsed method in try/catch blocks because if an unhandled exception happens there, your timer won't start again.
Another method I've used before is to use a lock in your Elapsed event:
var myLock = new Object();
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
lock (myLock) {
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
}
This way, two instances of the Elapsed event cannot run at the same time. However, there is a caveat: If the task takes longer than two or more iterations of the timer, then you can have iterations adding up in the background. For example, if your timer elapses after 5 seconds, but your task takes 60 seconds to complete, by the time the first one finishes, you'll have 11 waiting.
Upvotes: 1
Reputation: 64931
Timer.Change
method giving Timeout.Infinite
and 0
as arguments will stop the timer (from MSDN):
If dueTime is zero (0), the callback method is invoked immediately. If dueTime is Timeout.Infinite, the callback method is never invoked; the timer is disabled, but can be re-enabled by calling Change and specifying a positive value for dueTime.
One possible and simple but yet powerful approach is stopping the timer until the whole tasks have ended, and then, start the timer again:
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
timerDoJob.Change(Timeout.Infinite, 0);
// Use a try-finally so if some tasks throws an exception
// the timer will be re-enabled again anyway
try
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
finally
{
timerDoJob.Change(0, 5000);
}
}
Upvotes: 1