2011-02-10 255 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的類的所有依賴項。