System.Threading.Timer interval in Windows Service

L

linesh.gajera

Hi Guys,

I am creating a Windows service that call a routine at given interval.
Once routine is complete, windows service should wait for 5 minutes and
then call the routine again. I was using System.Timers.Timer but i had
to remove it because of known bug(842739). Now i am using
System.Threading.Timer. It executes routine fine but the delay time is
sporadic, sometimes it executes routine after 5 minutes, sometimes 10
minuete, 13 minuntes. I want to wait exactly 5 mintes before it call
the routine. Here is my code snippet. I don't know how to fix it.


private Timer eventTimer;
private bool ProcessInProgress = false;

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
TimerCallback eventCallBack = new TimerCallback(this.OnTimer);
eventTimer = new
Timer(eventCallBack,this,System.Threading.Timeout.Infinite,System.Threading.Timeout.Infinite);

//Here window service should wait for 5 mintes before call the routine
eventTimer.Change(300000,0);
}

public void OnTimer(Object source)
{
if(ProcessInProgress == false)
{
//RunTMService routine is called
RunTMService();

//Once RunTMService routine is complete, timer should wait for 5
more minutes and exeucte the routine again.
eventTimer.Change(300000,0);
}
}

private void RunTMService()
{
try
{
ProcessInProgress = true;
//Here perform all database activites and business logic
}
catch{}
finally
{
ProcessInProgress = false;
}
}

I don't understand why Timer does not exeute exactly after 5 minutes.
It is very sporadic. Any clue? Direction?
 
G

Guest

Unfortunately, most timers like System.Threading.Thread.Sleep() are not very
precise as the time between triggers is dependant on a lot of things, so
having exact intervals can be extremely difficult.

Using timers, I would suggest dramatically decreasing the time and implement
some sort of check like checking the current time against time that your
worker function was last run (which you would have to note).

This way, if you’ve got your timer firing every say... 15 seconds, you are
far more likely to be woken nearer to your target time than you are with a 5
minute interval.

An improvement on this would be to move away from the timer completely and
implement it with a thread where you have a main loop, always looping with
the same logic as mentioned above, only if the condition is not met, a Sleep
call to cause the thread to sleep for a short period of time ( a matter of
seconds ideally) before checking again.

Brendan
 
G

Guest

Brendan Grant said:
Unfortunately, most timers like System.Threading.Thread.Sleep() are not very
precise as the time between triggers is dependant on a lot of things, so
having exact intervals can be extremely difficult.

That is true, but timers are can be trusted to be accurate within fractions
of a second, and certainly to not be out by seconds, or even minutes, as
indicated in the OP. I'd only hesitate to use a timer if the required
accuracy was greater than 100 ms (and there are timers for getting better
accuracy than that).

An error of 8 minutes is not due to the timers, but either the program
logic, or some deadly disturbance in the system.

I wrote this little console program to test the accuracy of
System.Threading.Timer. The first run, I set the timer interval to 1000 (ie.
1 sec), and it was typically being invoked with an accuracy of 0 to 60 ms
(mostly 0 - 30 ms). I did a second run, with an interval of 5 minutes, and
the accuracy was the same.

using System;
using System.Threading;

class TimerTest
{

static void Main()
{
TimerCallback timerDelegate = new TimerCallback(OnTimer);

// Create a timer to start immediately, and callback every 5
// minutes.
Timer timer = new Timer(timerDelegate, null, 0, 1000 * 60 * 5);

// Wait for ctrl-c to terminate this console app.
while (true)
{
};

}

static int count = 0;

static DateTime startTime = DateTime.Now;

// Timer callback
static void OnTimer(object state)
{
// Display the total time elapsed, in milliseconds,
// since we started.
TimeSpan span = DateTime.Now - startTime;
Console.WriteLine("Count = {0}, Time = {1}",count++,
span.TotalMilliseconds);
}
}

Output...

Count = 0, Time = 78.1245
Count = 1, Time = 300091.8294
Count = 2, Time = 600121.1592
Count = 3, Time = 900150.489
Count = 4, Time = 1200164.1939
Count = 5, Time = 1500193.5237
Count = 6, Time = 1800222.8535
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top