我在Windows服务项目中使用System.Threading.Timer
之前正在做一个小型测试项目。它工作得非常好,但计时器会在一两分钟后自行停止。
测试项目的完整来源是:
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();
}
}
}
}
目标显然是用当前时间更新标签。我注意到稍后更新停止了。为什么会这样?
答案 0 :(得分:37)
如果您需要Windows窗体上的计时器,请将System.Windows.Forms.Timer
放到表单上 - 没有理由使用System.Threading.Timer
,除非您需要超过55毫秒的分辨率。
定时器“停止”的原因是因为它被垃圾收集。您允许它超出Form1_Load
方法的范围,因为您只将它声明为局部变量。为了使计时器“保持活动”,它必须是表单类上的私有字段,以便GC知道它仍然需要。
换句话说:
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);
}
}
但同样,在这种情况下,使用System.Windows.Forms.Timer
更简单,System.Windows.Forms.Timer
是工具箱中的一个实际组件,您只需将其放到表单上即可。
编辑 - 正如评论现在所揭示的那样,如果这只是一个测试应用而且真正的应用程序在Windows服务中,那么无法使用System.Threading.Timer
为了那个原因。请记住,不要让{{1}}超出范围。
答案 1 :(得分:1)
垃圾收集器收集了计时器对象,你应该保留对它的引用。 这篇文章将有助于:http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
答案 2 :(得分:-1)
不应该。你的代码有问题吗? 编辑:我在谈论工具箱中的计时器。