2011-05-27 69 views
0

給定以下代碼,計時器將每隔一秒觸發PrintTimer函數,直到用戶按下一個鍵。C# - Timer的實例何時會被殺死?

問題1>定時器何時停止? 定時器默認爲後臺線程,所以它會在前臺線程終止後被終止。

問題2>如何以編程方式停止調用線程中的計時器?

class Program 
{ 
    // continue to call this function until the user presses a 
    // key to terminate the application 
    static void PrintTime(object state) 
    { 
     Console.WriteLine("Time is: {0}", 
     DateTime.Now.ToLongTimeString()); 
    } 
    static void Main(string[] args) 
    { 
     TimerCallback timeCB = new TimerCallback(PrintTime); 
     System.Threading.Timer t = new Timer(
      timeCB, 
      null, 
      0, 
      1000); 
     Console.WriteLine("Hit key to terminate..."); 
     Console.ReadLine(); 
    } 
} 

回答

4

回答1

眼下定時器將停止該程序退出,只有當。它不是真的坐在那裏使用後臺線程,但是當定時器事件發生時,回調將通過ThreadPool線程調用,後臺線程是

答案2

停止計時器是既可以作爲簡單:

t.Change(Timeout.Infinite, Timeout.Infinite); 

- 或 -

t.Dispose(); 

前者可以讓你重新啓動Timer與另一請致電Change,因爲後者將完全清理Timer

有關其行爲的更多詳細信息,我建議您閱讀Timer類的備註部分its MSDN documentation。例如,Dispose有一些棘手的時機,因爲Timer可能已經排隊等待線程池的通知回調,即使在調用Dispose之後,您仍然可以在技術上收到該線程池。

1

問題2看Timer.Enabled屬性和Timer.Close()方法

更新:我想的完整性我還應該提到的Timer.Stop()方法(它設置啓用爲false)

更新:當應每個選項使用?

一般來說有兩種情況:要麼擺脫計時器,從不計劃再次使用計時器,要麼暫停計時器,但計劃在某個時刻恢復計時器(或者至少希望選項是能夠恢復它)。

如果您正在擺脫計時器,那麼Dispose/Close是要採取的路線。至少應該調用Dispose,因爲當完成一個實現IDisposable的對象時,這是一個表現良好的程序應該執行的操作。

這就是說,當一個對象同時實現IDisposable和Close方法時,我認爲更好的方法是調用Close,因爲Close可能不僅僅是可用資源。例如,它可能會刷新緩衝區或做一些其他對象特定的事情。人們會期望一個Close方法來調用Dispose。理想情況下,關閉的文檔將明確聲明它調用Dispose(但Timer :: Close的文檔沒有說明它的作用)。

要暫時暫停並重新啓動計時器,您可以將Enabled屬性設置爲false,然後再次將其設置爲true。或者,您可以調用Stop(),然後調用Start()來恢復它。對於另一種技術我沒有偏好一種技術。

我想有人可能會說「停止和啓動」稍微更具可讀性,可能效率稍低(因爲它們依次設置爲「啓用」)。

+0

我有這麼多的選擇(即處置,關閉,停止),何時使用? -thx – q0987 2011-05-28 00:03:31

1

Timer是一次性的,所以你應該/必須打電話給Dispose就可以了。如果要重用它,也可以調用Stop,但Timer類中存在一個定期回調的錯誤,因此建議只處理它並從新定時器開始。

在你發佈的代碼中會發生什麼,定時器的終結器將會(在技術上可能)被調用,這將會終止它。

1

計時器將通過finzalizer運行進行清理。這是它變成garabage的時候,實際上從release to debug mode變化。

這裏我們可以運行使用WeakReference的測試:

internal class Program 
{ 
    // continue to call this function until the user presses a 
    // key to terminate the application 
    private static void PrintTime(object state) 
    { 
     Console.WriteLine("Time is: {0}", 
          DateTime.Now.ToLongTimeString()); 
    } 

    private static void Main(string[] args) 
    { 
     TimerCallback timeCB = new TimerCallback(PrintTime); 
     Timer t = new Timer(
      timeCB, 
      null, 
      0, 
      1000); 

     WeakReference wk = new WeakReference(t); 
     PrintStatus(wk); 

     Console.WriteLine("Hit key to terminate..."); 
     Console.ReadLine(); 

     t = null; 
     PrintStatus(wk); 
    } 

    private static void PrintStatus(WeakReference wk) 
    { 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     Console.WriteLine("Is timer alive? " + wk.IsAlive); 
    } 
} 
+0

WeakReference的用法是什麼? --thx – q0987 2011-05-28 00:07:47

+0

WeakReference允許你跟蹤和對象,並基本問它是否被收集。 http://msdn.microsoft.com/en-us/library/system.weakreference.aspx – 2011-05-28 00:11:24

1

在你的應用程序將永遠不會停止,直到你退出你的應用程序。

要以編程方式停止它,它取決於您使用的是哪個計時器。

System.Timers.Timer 

System.Threading.Timer 

如果第一個,您可以調用Stop方法。 如果第二個,你必須Dispose()它。

請注意,如果您在方法中啓動計時器並且不保留對其的引用,它將在垃圾收集時停止。

+1

我已經更新了我的OP,它的意思是System.Threading.Timer。 -謝謝 – q0987 2011-05-28 00:04:54