User999999
User999999

Reputation: 2520

Winservice - Timer: Same task being executed parallel

I've made a Window-Service which performs an action after each. We've declared the timer as follows:

using System.Timers;

....

Int32 myInterval = 60000 * (Convert.ToInt32(ConfigurationManager.AppSettings["lpInterval"].ToString()));
_myTimer = new Timer();
_myTimer.Interval = myInterval;
_myTimer.Elapsed += new ElapsedEventHandler(TimerElapsed);

    //Timer-Tick
private void TimerElapsed(object source, ElapsedEventArgs e)
{ PerformAction(); }

What have noticed: If PerformAction() takes longer then my interval (due to WCF-Services or Serverissues) then an new 'instance' of PerformAction is launched and executed. So the PerformAction is running twice (and parallel) to each other.

What is the cause of this? Why isn't the previous PerformAction being cancelled? Is the method PerformAction being executed Async?

I've found a workaround but I just don't understand the behavior...

Upvotes: 0

Views: 192

Answers (2)

Tsukasa
Tsukasa

Reputation: 6552

Before you run your action stop the timer then after perform action start the timer again

private void TimerElapsed(object source, ElapsedEventArgs e)
{ 
    _myTimer.Stop();
    PerformAction();
    _myTimer.Start();
}

System.Timers

http://msdn.microsoft.com/en-us/library/system.timers.timer.elapsed(v=vs.110).aspx

the Elapsed event is raised on a ThreadPool thread. If the processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.

Elapsed events can occur after the Dispose or Stop method has been called or after the Enabled property has been set to false, because the signal to raise the Elapsed event is always queued for execution on a thread pool thread. One way to resolve this race condition is to set a flag that tells the event handler for the Elapsed event to ignore subsequent events.

Upvotes: 1

Servy
Servy

Reputation: 203802

It's simply a design decision of the timer. It has a number of possible resolutions, ranging from firing the events in parallel, queuing the handlers until immediately after the previous handler finishes, to skipping that particular event entirely. The designers choose that option. They could just as easily have chosen another, as designers of certain other timers have done.

As for why it's not cancelled, cancelling code non-cooperatively is very dangerous and extremely error prone, and implements of tick handlers are generally not going to feel the need to implement cooperative cancellation (they could do so using the existing implementation if they really wanted to anyway) so this is not really a practical option.

Upvotes: 1

Related Questions