2012-12-28 20 views
3

我有2 定時器System.Timers.Timer)正在運行,兩個定時器Elapsed-Events已委託訂閱。這兩種方法(在訂閱的委託中)都在處理相同的對象(例如列表中的列表和對象)。定時器事件的委託是否被調用爲線程安全的進程?

說定時器Elapsed事件被調用在同一時間

代表是否會在不同的線程中運行?或者他們會一個接一個地被叫? 我應該讓代碼線程安全,並使用鎖定嗎?

+1

你在說什麼'Timer'類? – CodesInChaos

+1

[文檔](http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.100%29.aspx)說:*「如果SynchronizingObject屬性爲null,則如果處理Elapsed事件的持續時間超過間隔時間,則可能會在另一個ThreadPool線程上再次引發該事件。在這種情況下,事件處理程序應該是可重入的。「*不完全描述您的情況,但很好的線索表明事件不會在同一個線程中排隊。 –

+0

的意思是:[System.Timers.Timer](http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.100%29.aspx) –

回答

1

它們將作爲ThreadPool中的工作項目排隊,因此,它們有可能會同時執行。確保這種情況不會發生的一種方法是隻安排一個計時器回叫,並且到infinteSystem.Threading.Timer支持這種方式)的經常性時間,並在工作完成時重新計劃。

3

我假設你指的是System.Timers.Timer而不是System.Windows.Forms.Timer。正如文檔所述:

基於服務器的Timer專用於多線程環境中的工作線程。服務器定時器可以在線程之間移動以處理引發的Elapsed事件,從而比按時提升事件的Windows定時器更準確。

沒有什麼能保證你兩個不同的線程不會爲兩個不同的定時器提高Elapsed事件。最好讓你的代碼是線程安全的。

我添加了一段簡短的代碼片段,以顯示Elapsed的多個回調可以同時調用(在這種情況下,導致死鎖 - Debug.WriteLine永遠不會被調用)。

var _lock = new object(); 
GC.KeepAlive(_lock); 
var timer1 = new Timer(100); 
var timer2 = new Timer(200); 
timer1.Elapsed += delegate 
{ 
    lock (_lock) 
     Thread.Sleep(-1); 
}; 
timer2.Elapsed += delegate 
{ 
    lock (_lock) 
     Debug.WriteLine("Hello world."); 
}; 
timer1.Start(); 
timer2.Start(); 
1

定時器回調(您不指定特定的類/名稱空間)始終在單獨的線程中調用。所以你應該讓你的代碼線程安全。 他們是否會被稱爲「在同一時間」或隨後的過程取決於他們的間隔設置。
使用相同的間隔集合,首先調用哪個回調函數幾乎是非確定性的。