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个线程在最后一次"更新"后终止。

我怎样才能使它无限地工作?

c# System.Threading.Timer递归更新

在回调中实例化一个新的计时器似乎很奇怪。一个更现实的例子是在计时器回调中执行工作。此外,您似乎不正确地调用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确保只要这些计时器被启用,它们就保持被引用。但是不要使用它,否则它不是一个很好的计时器。