Reputation: 63
Folks, I am implementing a routine in a Windows service .NET based, and am using a Threading.Timer task within
protected override void OnStart(string[] args)
{
base.OnStart(args);
_startupTask = Task.Factory.StartNew(StartupAction, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
in my StartupAction i am defning a Threading.Timer as follows:
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
One would think that this is a no brainer, but for some reason it is not always working (works on some PCs but not on others).
Would anyone know what would be the culprit or the environment dependency?
Thanks
When Timers go out of scope callbacks wont be triggered. See answers below
Upvotes: 1
Views: 723
Reputation: 8124
I think your StartupAction method is simply ending (the fact that it goes out of scope and get's garbage collected is a by-product, in my opinion).
You need to modify your StartupAction method to keep it alive.
Try adding something like: while(true) { Thread.Sleep(1000); }
to keep the thread alive.
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
while(true) { Thread.Sleep(1000); } //this is the simplest logic to keep the thread alive
}
Upvotes: 0
Reputation: 29668
Your problem is in that you use a Task
and create the timer entirely contained in the task action:
private void StartupAction()
{
System.Threading.Timer infamousTimer;
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
What I think is happening is once the StartupAction
completes the timer goes out of scope and is disposed/GC'd.
Instead move the timer variable outside:
private Timer infamousTimer;
private void StartupAction()
{
infamousTimer = new System.Threading.Timer(new TimerCallback(runMeEveryHour), null, new TimeSpan(0), new TimeSpan(1, 0, 0));
}
The advantage here is also in OnStop
you can dispose of the timer cleanly.
Of course, why even do this in a Task
? Seems overkill when just doing it in OnStart
would work just as well.
I'd also like to point out that if all the service does is run a timer, you'd be better off with a scheduled task, but I'm making an assumption there.
See this blog post on why.
Upvotes: 4