BoredOfBinary
BoredOfBinary

Reputation: 853

System.Threading.Timer not continuous

I am having troubles with creating a continuous timer. There are multipule staggered threads created on timers which will run for some time then come to a complete stop. The maximum threads I am allowing is 5 and the timer interval is set to 10000. So in theory there would be 1 thread executed every 2 seconds.

This happens for a while, but then it stops. currently I am testing in a console app and writing the responses to the app.

I am not exactly sure what is happening here

internal class EngineThreadGenerator
{
    private readonly AutoResetEvent _autoEvent;
    private readonly Action<string, string> _processQueueDelegate;
    private readonly Action<string, string> _purgeQueueDelegate;

    private void createAllowedEmailThreads()
    {
        for (int counter = 0; counter < AppSettings.ProcessQueueAllowedThreads; counter++)
        {
            EmailThread _emailThread = new EmailThread(_collection, _processQueueDelegate, _purgeQueueDelegate);
            TimerCallback _timerCallback = _emailThread.InitEmailThread;
            Timer _stateTimer = new Timer(_timerCallback, _autoEvent, 0, AppSettings.ProcessIntervalInMilliseconds);

            pauseLoop();
        }
    }

Any help here is greatly appreciated! Cheers!

Upvotes: 9

Views: 2775

Answers (2)

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391664

The reason your timers are dying after 3 minutes is that you have a lot of memory available.

Which means the garbage collector takes about 3 minutes to get to your objects before collecting them.

You're supposed to keep a reference to the timer for the duration of its lifetime. Since you're not doing that, the timer is eligible for garbage collection as soon as your loop ends.

3 minutes later, or whenever GC gets around to it, the timer is collected, and your code stops executing.

So, keep a reference to the timer object, and you should be all set.

Here's a simple LINQPad script to test with:

void Main()
{
    new Timer(Callback, null, 0, 1000);
    Thread.Sleep(5000);
    Debug.WriteLine("collecting");
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    Debug.WriteLine("collected");
    Thread.Sleep(5000);
}

static void Callback(object state)
{
    Debug.WriteLine("callback");
}

Observe that once the main thread runs GC, the callback stops. If, on the other hand, you make a copy of the timer into a field:

Timer _Timer;

void Main()
{
    _Timer = new Timer(Callback, null, 0, 1000);
    ...

the timer keeps on ticking past GC.

Upvotes: 10

CodingWithSpike
CodingWithSpike

Reputation: 43748

Maybe it just isn't in this code snippit, but do you ever decrement counter?

Upvotes: 0

Related Questions