c# System.Threading.Timer递归更新
本文关键字:递归 更新 Timer Threading System | 更新日期: 2023-09-27 18:19:23
我有一个曾经的计时器,每15秒调用一个函数,它的工作为前5次,但然后不发生第6次,即使它是创建的,任何想法?
处理时间可能超过15秒,如果是这样,线程A可能正在处理数据,而线程B发出新的数据请求。在线程A处理完成之前,线程B不能启动。
const int DATAREFRESH = 15000;
void RequestUpdate()
{
// Some data processing goes here
Console.WriteLine("Update");
// Set the timer
Timer t = new Timer(new TimerCallback(TimeOutCallback), null, DATAREFRESH, Timeout.Infinite);
}
private void TimeOutCallback(object state)
{
RequestUpdate();
}
在Output窗口,"Update"显示了5次,之后就没有了。它没有冻结,我看到~8个线程在最后一次"更新"后终止。
我怎样才能使它无限地工作?
在回调中实例化一个新的计时器似乎很奇怪。一个更现实的例子是在计时器回调中执行工作。此外,您似乎不正确地调用Timer
构造函数。如果您希望回调以固定的间隔执行(在您的示例中为15秒),您可以使用以下命令:
const int DATAREFRESH = 15000;
private Timer _timer;
void RequestUpdate()
{
// Set the timer
_timer = new Timer(TimeOutCallback, null, 0, DATAREFRESH);
}
private void TimeOutCallback(object state)
{
// Some data processing goes here
Console.WriteLine("Update");
}
还请注意我是如何反转传递给计时器的参数的,以便它每15秒执行一次回调。
是,垃圾收集器已删除计时器对象。这个问题是从将计时器引用声明为局部变量开始的。RequestUpdate()方法退出后,就没有对计时器的引用了。甚至回调也不提供引用,这有点不寻常,但它与具有静态回调方法的计时器一致,并避免了泄漏。
简单的解决方法是使它成为类的一个字段:
private Timer dataRefreshTimer;
void RequestUpdate()
{
dataRefreshTimer = new Timer(new TimerCallback(TimeOutCallback), null, 0, DATAREFRESH);
}
确保计时器至少与包含回调方法的类一样长。
值得注意的是,System.Timers.Timer类没有同样的问题。CLR确保只要这些计时器被启用,它们就保持被引用。但是不要使用它,否则它不是一个很好的计时器。