2010-03-12 41 views
10

從Windows服務使用System.Threading.Timer(.NET 2.0)時,我們遇到了以下問題。C#計時器在間隔時間之前被解僱

  1. 大約有12個不同的計時器對象.
  2. 每個計時器都有到期時間和間隔。這是正確設置的。
  3. 觀察到在3到4小時後,定時器在它們的間隔過去之前開始發信號。例如,如果計時器應該在4:59:59發出信號,則會在7秒前的4:59:52發出信號。

有人能告訴我這種行爲的原因是什麼,解決方法是什麼?

謝謝, Swati

回答

0

也許再調度,需要一些秒即可完成操作後進行。或者你不控制這個?

0

這不可能控制,因爲它依賴於系統的速度,如果你有超級計算機則有可能是沒有足夠的差異,但如果你有正常的PC然後就會出現後不久在定時間隔差執行。

希望這會有所幫助。

9

大問題...和這裏的原因:

「時序」是一件棘手的事情,當它涉及到計算機......你可以永遠依靠「間隔」是完美的。有些計算機會每隔14到15毫秒就會對計時器進行「打勾」,其中一些頻率比較頻繁,一些頻率較低。

所以:

Thread.Sleep(1); 

可能從1到30毫秒的任何地方運行。相反,如果您需要更精確的計時器 - 您必須捕獲開始時的DateTime,然後在計時器中,您必須通過減去DateTime.Now和原始時間來檢查它是否爲「時間來運行「你的代碼。

下面是你需要做的一些示例代碼:

DateTime startDate = DateTime.Now; 

然後,設置爲1毫秒的間隔啓動定時器。然後,在你的方法中:

if (DateTime.Now.Subtract(startDate).TotalSeconds % 3 == 0) 
{ 
    // This code will fire every 3 seconds. 
} 

上面的代碼將每3秒忠實地觸發一次。你可以讓它運行10年,並且它每3秒鐘仍然會啓動。

+0

我知道這只是一個例子,但是你不會將計時器間隔增加到100甚至500毫秒之類嗎?我知道你可能會失去一點準確性,但是當你每3秒鐘只需要一個結果時,這不會比每秒鐘發射1000次定時器更好嗎? – 2010-03-12 14:12:43

6

蒂莫西的解釋很有說服力,但System.Threading.Timer已經以這種方式工作。至少在Rotor實現中,它使用GetTickCount()返回的值來計算下一次回調到期的時間。真正的CLR不太可能這樣做,它更可能使用CreateTimerQueueTimer()。不過,這個API函數也可能依賴於由時鐘滴答中斷遞增的內部滴答。

爭議的焦點是內部時鐘如何剔(通過的GetTickCount()和環境返回。TickCount)與絕對掛鐘時間保持同步(由DateTime.Now返回)。不幸的是,這是您機器上的HAL實現細節,即硬件抽象層。機器製造商可以提供定製的HAL,這是一種可以與機器的BIOS和芯片組協同工作的定製HAL。

如果機器有兩個定時源,一個時鐘芯片被設計用來跟蹤掛牆時間並且即使拔下機器電源也能保持滴答狀態,另一個頻率可以分配到芯片組上提供時鐘中斷。原來的IBM AT PC以這種方式工作。時鐘芯片通常可以被信任,如果時鐘不準確,時鐘將被關閉。芯片組不能,削減振盪器的質量是一個簡單的方法來節省一分錢。

解決您的問題,避免您的計時器長時間,並從回調中的DateTime.Now重新計算下一個到期時間。

+0

感謝您的幫助。重新計算定時器可能會解決我的問題。我要去嘗試一下。再次感謝 !! – 2010-03-15 07:09:31