System.Threading.Timer not firing after some time

Viewed 16592

I have a windows service application. And debugging it by running in console mode.

Here http://support.microsoft.com/kb/842793 it is written that Timers.Timer has a bug and not firing in windows services. And workaround is to use Threading.Timer And this article is for .NET 1.0 and 1.1

I am using .NET 4 but after some time Threading.Timer also doesn't fire. So what can be the reason for this? And what can you suggest as a workaround?

Thanks,

Best Regards

EDIT: I changed timer from Threading.Timer to Timers.Timer and it is working without any problem.

6 Answers

Here is how you can use RegisterWaitForSingleObject:

When you have code registering a timer like that:

const int scheduledPeriodMilliseconds = 20000;
new Timer(ServiceBusTimerCallback, parameters, 0, scheduledPeriodMilliseconds);

private static void ServiceBusTimerCallback(object params)
{
}

You can have this:

const int scheduledPeriodMilliseconds = 20000;
var allTasksWaitHandle = new AutoResetEvent(true);

ThreadPool.RegisterWaitForSingleObject(
    allTasksWaitHandle,
    (s, b) => { ServiceBusTimerCallback(parameters); },
    null,
    scheduledPeriodMilliseconds,
    false);

You can use allTasksWaitHandle.Set() after ServiceBusTimerCallback to inform user that task was done, so it will run task again immediately. This code posted above will run task after timeont will pass, so every 20 seconds.

I implemented it in WebAPI project and it works great.

Here is an experimental demonstration that a non rooted System.Threading.Timer is eligible for garbage collection. The mere fact that it is scheduled for future execution, does not prevent it from being recycled.

WeakReference timer = StartTimer();
Console.WriteLine($"Before GC.Collect - IsAlive: {timer.IsAlive}");
GC.Collect();
Console.WriteLine($"After GC.Collect  - IsAlive: {timer.IsAlive}");
Thread.Sleep(1000);
Console.WriteLine($"Finished");

static WeakReference StartTimer()
{
    Timer timer = new(_ => Console.WriteLine("Callback!"), null, 500, -1);
    return new(timer);
}

Output:

Before GC.Collect - IsAlive: True
After GC.Collect  - IsAlive: False
Finished

Online demo.

Related