2011-02-10 254 views
3

这是使用System.Timers.Timer的正确方法吗? 我的意思是...我创建计时器,设置要在Elapsed事件上调用的时间间隔和方法。System.Timers.Timer生命周期

double ms = 1000; 
var t = new System.Timers.Timer(ms); 
t.AutoReset = false; 
t.Elapsed += (sender, e) => { runTask(); }; 
t.Start(); 

下一步是什么?应该在定时器上处理一个呼叫吗?我想我不能,或者Elapsed事件永远不会发生。 我应该在一些全局变量中注册Timer以避免丢失对它的引用,因此GC可以在调用Elapsed之前处置该计时器? 如果是这样,一旦处理了Elapsed事件(因此我的任务已经执行),我该如何处理Timer呢?

回答

1

简短的答案是你不需要做任何事情。当功能超出范围时,它将由垃圾收集器收集。如果你想要它可用,然后在类中声明它。


通常,当您在类级别声明一个计时器时,它会在GC处置时由GC收集。然而,当你有你的定时器声明的函数,则定时器仍然运行,但如果你正在执行一个很长的过程,然后GC可以热映处置它,所以你需要使用

GC.KeepAlive(youtimer_Instance); 

看一看结束用于参考此场景的Timer's Documentatio n。

在示例代码中的注释说:


     Normally, the timer is declared at the class level, 
     so that it stays in scope as long as it is needed. 
     If the timer is declared in a long-running method, 
     KeepAlive must be used to prevent the JIT compiler 
     from allowing aggressive garbage collection to occur 
     before the method ends. 
+0

如果Timer在Form A上创建并且用户退出应用程序(如果任务尝试访问表单控件时发生异常,它发生在我身上一次),这可能会产生问题。 – 2011-02-10 10:38:43

+0

@Mohib Sheth:我的回答是如何保护定时器免于被处置..明显地停止它,你将需要调用Stop()。如果您可以在需要时取消订阅您的事件处理程序,那也更好。亚历克西斯已经解释过它.... – 2011-02-10 13:44:14

0

您应该在窗体/页面的关闭/卸载或您认为合适的任何位置调用t.Stop()。如果让它继续运行,它将不必要地利用资源,并且在关闭应用程序时可能会遇到异常。

4

如果你是一个在长期运行过程中使用的定时器(如Web应用程序或Windows服务),如果你不想让存储泄漏,如果您希望垃圾回收器能够回收为Timer对象分配的内存,您需要确保您取消了从Timer的过期事件处理程序订阅。

System.Timers.Timer实现了IDisposable,这里的指导是如果你有一个实现IDisposable的类,那么任何实现了IDisposable的对象的依赖关系的类都应该实现IDisposable本身,并在调用Dispose()方法时调用对象它本身被称为。

一个完美的例子就是System.Timers.Timer。它使用System.Threading.Timer封面的下面,如果你在看反射,你可以看到System.Timers.Timer

public void Dispose() 
{ 
    this.timerBase.Dispose(); 
} 

的Dispose方法如下这里,timerBase简直的System.Threading的一个实例。定时器,因此Dispose调用级联到实现IDisposable的类的所有依赖项。