Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

c# - Why does System.Threading.Timer stop on its own?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...