2013-06-01 22 views
0

我正在使用兩個System.Threading.Timer實例來關閉兩個週期性重複的任務。正在進行回調時禁用System.Threading.Timer實例

我的問題是:如果定時器被禁止,但在那個時間點,該計時器上執行一個線程它的回調,那麼Main方法將退出或者它會等待執行回調來完成?

在下面的代碼中,Method1RunCount使用鎖定語句進行讀取和寫入同步(這部分代碼未顯示在下面)。 timer1的回調會在每次運行結束時將Method1RunCount遞增1。

static void Main(string[] args) 
{ 
    TimerCallback callback1 = Method1; 
    System.Threading.Timer timer1 = new System.Threading.Timer(callback1,null,0, 90000); 
    TimerCallback callback2 = Method2; 
    System.Threading.Timer timer2 = new System.Threading.Timer(callback2, null, 0, 60000); 
    while (true) 
    { 
     System.Threading.Thread.Sleep(250); 
     if (Method1RunCount == 4) 
     { 
       //DISABLE the TIMERS 
       timer1.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); 
       timer2.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); 
       break; 
     } 
    } 
} 

回答

2

這種類型的代碼往往意外地工作,計時器的週期足夠大,以避免Method1RunCount變量上的線程競爭。縮短週期,並且存在真正的危險,即主線程根本看不到「4」值。當處理器負載過重並且主線程沒有按計劃進行時,可能性會大大降低。當主線程正在等待處理器時,定時器的回調可以執行多次。完成缺少值增加到4.注意語句實際上並不妨礙這一點,它並未被主線程鎖定,因爲它可能正在睡眠。

對於Method2運行的頻率,您也沒有合理的猜測。不僅僅因爲它具有完全不同的計時器週期,而且基本上是因爲它根本不同步到Method1或Main方法執行。

您通常會在Method1的處增加Method1RunCount。否則不保證Method1不會中止。它在一個線程池線程上運行,它們的Thread.IsBackground屬性始終設置爲true。因此,當主線程退出時,CLR將輕易放棄它們。這又不會偶然導致問題。

如果方法1完全執行4次是絕對必要的,那麼確保Method1執行計數的簡單方法是。調用方法內的Timer.Change()很好。使用類AutoResetEvent讓主線程知道它。現在不再需要睡眠了。您仍需要鎖定才能確保Method1在執行時不能重新輸入。 知道你得到線程同步錯誤的一個好方法是當你看到自己使用Thread.Sleep()時。

0

從文檔上System.Threading.Timerhttp://msdn.microsoft.com/en-us/library/system.threading.timer.aspx):

當不再需要一個計時器,用Dispose方法以釋放由計時器所保持的 資源。請注意,調用 Dispose()方法重載之後可能會發生回調,因爲定時器會將線程池線程執行的 回調調用回來。您可以使用 Dispose(WaitHandle)方法重載等待,直到所有回調已完成 。

相關問題