2011-03-16 31 views
1

我碰到一些代碼,迷迷糊糊類似如下:正確使用System.Threading.Timer

private void SomeCallBack(object state) 
    { 
     lock (_lock) 
     { 
      try 
      { 
       if (_timer == null) 
        return; 

       _timer.Dispose(); 
       // do some work here 
      } 
      catch 
      { 
       // handle exception 
      } 
      finally 
      { 
       _timer = new Timer(SomeCallBack, state, 100, Timeout.Infinite); 
      } 
     } 
    } 

我不明白,每次執行回調時重建定時器的目的。我認爲代碼試圖實現的是一次只有一個線程可以執行這項工作。但是這個鎖是否足夠?

此外,根據MSDN,

注意,可以在Dispose()方法重載後出現回調,被稱爲

是否有這樣做有什麼好處? 如果是這樣,那麼在處置和創建計時器時,這些好處是否合理呢?

感謝您的幫助。

回答

1

看起來代碼想要一個接近週期的定時器(由於定時器到期和創建新定時器之間的處理引入了抖動,所以不完全是週期性的)。處理和重新創建定時器確實是不必要的開銷。 Change方法會更好。

對null的檢查也很好奇;在其他地方,必須有代碼將_timer設置爲null才能起作用。

+0

定時器在函數中設置爲null以停止定時器。如果你只是將間隔設置爲100就不會達到同樣的效果?你甚至不需要使用'Change()'。狀態在函數中沒有修改,所以重新創建定時器的目的不是爲實際工作傳遞新的參數。 – zyq

+0

這個答案是正確的。該代碼正在創建一個一次性定時器。結果是一個回調結束和下一個回調開始之間會有100 ms的延遲。但是由於該時間段設置爲'Timeout.Infinite',所以定時器不會再次啓動。通過調用'_timer.Change(100,Timeout.Infinite)'可以達到同樣的效果,只是它不能處理定時器爲'null'的情況。在現有的代碼中,如果定時器爲空,則不進行處理,但在「finally」中創建新的定時器。 –

+0

此外,在這裏使用鎖是很好奇的。除非有多個使用此回調的定時器,否則它們將無法同時被多個線程調用。定時器是一次性的,使得重入電話成爲不可能。 –

0

重新創建定時器的原因是定時器回調中的代碼比定時器週期執行需要更長的時間。在這種情況下,回調的多個實例將同時運行。