views:

647

answers:

2

Hi there,

I'm doing a small test project before I use System.Threading.Timer in a Windows Service project. It's working wonderfully, however the timer stops on its own after a minute or two.

The full source for the test project is:

using System;
using System.Windows.Forms;
using System.Threading;

namespace studyTimers {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            TimerCallback timerDelegate = new TimerCallback(tick);
            System.Threading.Timer testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000);
        }

        void tick(Object obj) {
            if (label1.InvokeRequired) {
                label1.Invoke(new MethodInvoker(() => tick(obj)));
            } else {
                label1.Text = DateTime.Now.ToString();
            }
        }
    }
}

The goal is obviously to update a label with the current time. I am noticing that updating stops after a bit. Why would this be?

+12  A: 

If you need a timer on a Windows Form then drop a System.Windows.Forms.Timer onto the form - there's no reason to use a System.Threading.Timer unless you need better resolution than 55 ms.

The reason the timer "stops" is because it's being garbage-collected. You're allowing it to go out of scope in the Form1_Load method because you only declare it as a local variable. In order to keep the timer "alive", it needs to be a private field on the form class so that the GC knows it's still needed.

In other words:

public partial class Form1 : Form
{
    private System.Threading.Timer testTimer;

    ...

    public void Form1_Load(object sender, EventArgs e)
    {
        TimerCallback timerDelegate = new TimerCallback(tick);
        testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000);
    }
}

But again, in this case it's simplier to use System.Windows.Forms.Timer, which is an actual component in the toolbox that you can just drop onto the form.


Edit - As the comments now reveal, if this is just a test app and the real application is in a Windows Service, you cannot use System.Windows.Forms.Timer for that. Just remember not to let your System.Threading.Timer go out of scope.

Aaronaught
That's actually what the timer in the service is using, and it isn't firing. This is just a small test project.
Tom the Junglist
@Tom the Junglist : you shouldn't use a forms.timer in a service....
Mitch Wheat
Actually, Aaronaught is correct... moving the variable declaration into the class body fixed it.
Tom the Junglist
@Mitch: Yeah, that was my own ignorance
Tom the Junglist
A: 

It shouldn't. Is there a problem with your code? Edit: I was talking about the Timer that is in the toolbox.

Bloodyaugust