2012-01-04 63 views
1

我有一个一次Timer,每15秒调用一次函数,它可以在前5次运行,但是对于第6次运行,即使创建它,任何想法都不会过去。C#System.Threading.Timer递归更新

处理时间可能需要超过15秒,如果是的话,线程A可能正在处理数据,而线程B发出新的数据请求。线程B在线程A的处理完成之前无法启动。

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(); 
} 

在输出窗口中,“更新”显示5次,然后在此之后没有任何内容。它没有冻结,我看到〜8个线程在最后一次“更新”后终止。

我怎样才能使这个工作无限?

+0

请使用能够描述你正在试图解决这个问题的标题。 – 2012-01-04 22:11:07

+0

你正在使用哪一个Timer类? – phoog 2012-01-04 22:16:07

+0

为什么不创建一个计时器实例并在回调中重置它? – phoog 2012-01-04 22:16:42

回答

7

从回调中实例化一个新的定时器似乎很奇怪。一个更现实的例子是你正在执行定时器回调中的工作。此外,您似乎错误地调用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秒。

+0

是的,但后来我想再次启动它...... – craig1231 2012-01-04 22:13:51

+2

@ craig1231,请注意我是如何颠倒参数的:'new Timer(TimeOutCallback,null,0,DATAREFRESH);'。现在定时器会定期执行回调。 – 2012-01-04 22:16:27

+0

这看起来像沿着正确的线条,但我已经更新了上面的问题。 – craig1231 2012-01-04 22:27:04

2

是,垃圾收集器已删除计时器对象。这个问题得到了通过声明定时器引用作为局部变量开始。在RequestUpdate()方法退出后,没有引用留给定时器。即使回调提供了一个引用,有点不寻常,但它使得它与具有静态回调方法并避免泄漏的定时器一致。

简单的解决方法是使你的类的字段:

private Timer dataRefreshTimer; 

void RequestUpdate() 
{ 
    dataRefreshTimer = new Timer(new TimerCallback(TimeOutCallback), null, 0, DATAREFRESH); 
} 

这确保了计时器的生活至少只要包含回调方法的类。

值得注意的是System.Timers.Timer类没有这个问题。 CLR确保这些定时器只要启用就保持引用状态。但不要使用它,否则它不是一个很好的计时器。