为什么System.Threading.Timer自行停止?

时间:2022-09-09 20:36:22

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.

在Windows服务项目中使用System.Threading.Timer之前,我正在做一个小型测试项目。它工作得非常好,但计时器会在一两分钟后自行停止。

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?

显然,目标是用当前时间更新标签。我注意到稍后更新停止了。为什么会这样?

3 个解决方案

#1


36  

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.

如果你需要Windows窗体上的计时器,然后将System.Windows.Forms.Timer放到窗体上 - 没有理由使用System.Threading.Timer,除非你需要更好的分辨率超过55毫秒。

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.

计时器“停止”的原因是因为它被垃圾收集。您允许它超出Form1_Load方法的范围,因为您只将它声明为局部变量。为了使计时器“保持活动”,它必须是表单类上的私有字段,以便GC知道它仍然需要。

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.

但同样,在这种情况下,使用System.Windows.Forms.Timer更简单,它是工具箱中的一个实际组件,您可以将其放到表单上。


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.

编辑 - 正如评论现在显示的那样,如果这只是一个测试应用程序并且真正的应用程序在Windows服务中,则不能使用System.Windows.Forms.Timer。请记住不要让你的System.Threading.Timer超出范围。

#2


0  

Garbage collector collected the timer object, you should keep a reference to it. this post will help: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

垃圾收集器收集了计时器对象,你应该保留对它的引用。这篇文章将有所帮助:http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

#3


-1  

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

它不应该。你的代码有问题吗?编辑:我在谈论工具箱中的计时器。

#1


36  

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.

如果你需要Windows窗体上的计时器,然后将System.Windows.Forms.Timer放到窗体上 - 没有理由使用System.Threading.Timer,除非你需要更好的分辨率超过55毫秒。

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.

计时器“停止”的原因是因为它被垃圾收集。您允许它超出Form1_Load方法的范围,因为您只将它声明为局部变量。为了使计时器“保持活动”,它必须是表单类上的私有字段,以便GC知道它仍然需要。

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.

但同样,在这种情况下,使用System.Windows.Forms.Timer更简单,它是工具箱中的一个实际组件,您可以将其放到表单上。


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.

编辑 - 正如评论现在显示的那样,如果这只是一个测试应用程序并且真正的应用程序在Windows服务中,则不能使用System.Windows.Forms.Timer。请记住不要让你的System.Threading.Timer超出范围。

#2


0  

Garbage collector collected the timer object, you should keep a reference to it. this post will help: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

垃圾收集器收集了计时器对象,你应该保留对它的引用。这篇文章将有所帮助:http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

#3


-1  

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

它不应该。你的代码有问题吗?编辑:我在谈论工具箱中的计时器。