2015-04-18 87 views
2

我目前正在研究一個時間敏感的程序,其中重要的是我每秒都要從設備讀取數據。 我目前正在使用這個定時器,但是我發現時間穩定增加了1 ms pr tick的時間間隔。這可能會導致問題,因爲該程序將運行很長時間。System.Timers.Timer穩步增加間隔

Read Exe Time代碼需要多長時間才能執行。

Performing reading是在開始每個過去的事件。我怎麼能確保時鐘不會增加,我可以理解,蜱可能不會在確切的毫秒,但我繼續攀登似乎很奇怪。而且我的代碼不需要完整的1000毫秒來執行,所以不是這樣。在16.6分鐘之後,讀數會被推遲一秒鐘。

Read Exe Time: 574.0637 ms 
Performing reading: 22:58:39.696 
Read Exe Time: 571.9422 ms 
Performing reading: 22:58:40.697 
Read Exe Time: 595.5333 ms 
Performing reading: 22:58:41.697 
Read Exe Time: 566.2602 ms 
Performing reading: 22:58:42.698 
Read Exe Time: 568.2275 ms 
Performing reading: 22:58:43.698 
Read Exe Time: 569.7573 ms 
Performing reading: 22:58:44.700 
Read Exe Time: 561.655 ms 
Performing reading: 22:58:45.701 
Read Exe Time: 567.8385 ms 
Performing reading: 22:58:46.702 
Read Exe Time: 584.8305 ms 
Performing reading: 22:58:47.703 
Read Exe Time: 588.754 ms 
Performing reading: 22:58:48.703 
Read Exe Time: 560.8154 ms 
Performing reading: 22:58:49.704 
Read Exe Time: 567.9324 ms 
Performing reading: 22:58:50.705 
Read Exe Time: 579.1354 ms 
Performing reading: 22:58:51.706 
Read Exe Time: 563.0227 ms 
Performing reading: 22:58:52.707 
Read Exe Time: 569.557 ms 
Performing reading: 22:58:53.708 
Read Exe Time: 560.707 ms 
Performing reading: 22:58:54.708 
Read Exe Time: 574.6268 ms 
Performing reading: 22:58:55.709 
Read Exe Time: 570.4872 ms 
Performing reading: 22:58:56.710 
Read Exe Time: 574.8388 ms 
Performing reading: 22:58:57.710 
Read Exe Time: 573.2054 ms 
Performing reading: 22:58:58.710 
Read Exe Time: 578.6189 ms 
Performing reading: 22:58:59.711 
Read Exe Time: 565.7442 ms 
Performing reading: 22:59:0.711 
Read Exe Time: 564.7523 ms 
Performing reading: 22:59:1.712 
Read Exe Time: 575.8134 ms 
Performing reading: 22:59:2.713 
Read Exe Time: 570.9416 ms 
Performing reading: 22:59:3.713 
Read Exe Time: 573.1493 ms 
Performing reading: 22:59:4.714 
Read Exe Time: 570.2831 ms 
Performing reading: 22:59:5.714 
Read Exe Time: 568.2672 ms 
Performing reading: 22:59:6.715 
Read Exe Time: 586.5607 ms 
Performing reading: 22:59:7.715 
Read Exe Time: 588.0465 ms 
Performing reading: 22:59:8.715 
Read Exe Time: 574.1118 ms 
Performing reading: 22:59:9.716 

代碼

private void StartMeter() 
{ 
    this.Meter.Start(); 

    this.ReadingTime = new Timer(1000); 
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
    this.ReadingTime.Start(); 
} 

    private void PerformReading(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + "." + DateTime.Now.Millisecond); 

     // Code here 
    } 

更新: 如果我只是將時間設置爲999毫秒將它逐步減少,而不是

Performing reading: 23:4:50.527 
Read Exe Time: 562.7729 ms 
Performing reading: 23:4:51.527 
Read Exe Time: 566.8178 ms 
Performing reading: 23:4:52.527 
Read Exe Time: 562.3829 ms 
Performing reading: 23:4:53.526 
Read Exe Time: 567.9165 ms 
Performing reading: 23:4:54.526 
Read Exe Time: 561.1329 ms 
Performing reading: 23:4:55.525 
Read Exe Time: 562.9359 ms 
Performing reading: 23:4:56.525 
Read Exe Time: 560.4151 ms 
Performing reading: 23:4:57.524 
Read Exe Time: 561.0302 ms 
Performing reading: 23:4:58.524 
Read Exe Time: 561.5756 ms 
Performing reading: 23:4:59.524 
Read Exe Time: 565.2936 ms 
Performing reading: 23:5:0.523 
Read Exe Time: 561.8903 ms 
Performing reading: 23:5:1.523 
Read Exe Time: 561.8768 ms 
Performing reading: 23:5:2.523 
Read Exe Time: 562.3904 ms 
Performing reading: 23:5:3.523 
Read Exe Time: 562.3363 ms 
Performing reading: 23:5:4.523 
Read Exe Time: 561.6288 ms 
Performing reading: 23:5:5.523 
Read Exe Time: 560.4596 ms 
Performing reading: 23:5:6.522 
Read Exe Time: 562.34 ms 
Performing reading: 23:5:7.522 
Read Exe Time: 561.5994 ms 
Performing reading: 23:5:8.522 
Read Exe Time: 561.6811 ms 
Performing reading: 23:5:9.521 
Read Exe Time: 561.7427 ms 
Performing reading: 23:5:10.521 
Read Exe Time: 561.8044 ms 
Performing reading: 23:5:11.520 
Read Exe Time: 561.6246 ms 
Performing reading: 23:5:12.520 
Read Exe Time: 560.5753 ms 
Performing reading: 23:5:13.520 
Read Exe Time: 563.8604 ms 
Performing reading: 23:5:14.520 
Read Exe Time: 562.2606 ms 
Performing reading: 23:5:15.534 
Read Exe Time: 560.8377 ms 
Performing reading: 23:5:16.534 
Read Exe Time: 560.4553 ms 
Performing reading: 23:5:17.534 
Read Exe Time: 562.5534 ms 
Performing reading: 23:5:18.533 
Read Exe Time: 563.0269 ms 
Performing reading: 23:5:19.532 
Read Exe Time: 561.2851 ms 
Performing reading: 23:5:20.532 
Read Exe Time: 560.3442 ms 
Performing reading: 23:5:21.531 
Read Exe Time: 561.5201 ms 
Performing reading: 23:5:22.530 
Read Exe Time: 560.609 ms 
Performing reading: 23:5:23.530 

編輯:對於@PeterLuu

Performing reading: 22:44:45.13 
Performing reading: 22:44:45.449 
Performing reading: 22:44:45.879 
Performing reading: 22:44:46.320 
Performing reading: 22:44:46.761 
Performing reading: 22:44:47.192 
Performing reading: 22:44:47.631 
Performing reading: 22:44:48.74 
Performing reading: 22:44:48.577 
Performing reading: 22:44:49.49 
Performing reading: 22:44:49.637 

和代碼

private void StartMeter() 
{ 
    DateTime now = DateTime.UtcNow; 
    NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind); 

    this.Meter.Start(); 

    this.ReadingTime = new Timer(1000); 
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
    this.ReadingTime.Start(); 
    ReadingTime.Interval = GetTimeToNextSecond(); 
} 

private double GetTimeToNextSecond() 
{ 
    NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1); 
    var interval = NextTickTimeWholeSeconds - DateTime.UtcNow; 
    return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds; 
} 

private void PerformReading(object sender, ElapsedEventArgs e) 
{ 
    Console.WriteLine("Performing reading: " + DateTime.UtcNow.Hour + ":" + DateTime.UtcNow.Minute + ":" + DateTime.UtcNow.Second + "." + DateTime.UtcNow.Millisecond); 

    // My code takes about 500-600 ms 

    ReadingTime.Interval = GetTimeToNextSecond(); 
} 
+0

「_The時間穩定增加與1毫秒PR tick_間隔」也許我誤解,但聽起來該區間不增加或減少,這只是大約' 1.001'或'0.999's。 – AlexD

+0

是的,這是正確的,或1.0000-1.0001可能更正確 – Androme

+0

您可能想[更高分辨率的計時器](http://stackoverflow.com/questions/7137121/c-sharp-high-resolution-timer)。並可能不得不訴諸使用com調用。 –

回答

2

您可以根據時間爲下一秒(例如,如果只有890毫秒,直到點的下一秒),並且每次迭代重新啓動計時器以防止漂移。改編自Jared here的回覆。這不會精確到毫秒,但它可以防止你的時間漂移​​,事件總是會在「點」上發射。

編輯:刪除不必要的行 - 實際上不需要調用兩次Start(),只是更改間隔就足夠了,因爲更改間隔會重新啓動計時器。編輯2:進行一些更改以使其在邊緣情況下更準確(例如,防止連續多次觸發)。

public class Meter 
{ 
    private Timer ReadingTime; 
    private DateTime NextTickTimeWholeSeconds; 

    public Meter() { 
     DateTime now = DateTime.UtcNow; 
     NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind); 

     ReadingTime = new Timer(); 
     ReadingTime.AutoReset = false; 
     ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
     ReadingTime.Interval = GetTimeToNextSecond(); 
    } 

    public void StartMeter() 
    { 
     ReadingTime.Start(); 
    } 

    private double GetTimeToNextSecond() 
    { 
     NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1); 
     var interval = NextTickTimeWholeSeconds - DateTime.UtcNow; 
     return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds; 
    } 

    private void PerformReading(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + "." + DateTime.Now.Millisecond); 
     ReadingTime.Interval = GetTimeToNextSecond(); 
    } 
} 

示例輸出:

Performing reading: 18:11:47.10 
Performing reading: 18:11:48.4 
Performing reading: 18:11:49.10 
Performing reading: 18:11:50.6 
Performing reading: 18:11:51.9 
Performing reading: 18:11:52.5 
Performing reading: 18:11:53.10 
Performing reading: 18:11:54.5 
Performing reading: 18:11:55.9 
Performing reading: 18:11:56.7 
Performing reading: 18:11:57.7 
Performing reading: 18:11:58.7 
Performing reading: 18:11:59.7 
Performing reading: 18:12:0.8 
Performing reading: 18:12:1.7 
Performing reading: 18:12:2.6 

... about 50 seconds later ... 

Performing reading: 18:12:50.1 
Performing reading: 18:12:51.0 
Performing reading: 18:12:52.0 
Performing reading: 18:12:53.0 
Performing reading: 18:12:53.999 
Performing reading: 18:12:55.0 
Performing reading: 18:12:56.0 
Performing reading: 18:12:56.999 
Performing reading: 18:12:58.0 
Performing reading: 18:12:59.0 
Performing reading: 18:13:0.0 
Performing reading: 18:13:0.999 
Performing reading: 18:13:2.0 
Performing reading: 18:13:3.1 
Performing reading: 18:13:4.0 
Performing reading: 18:13:5.0 
Performing reading: 18:13:6.0 
Performing reading: 18:13:6.999 
Performing reading: 18:13:8.0 
Performing reading: 18:13:9.0 
Performing reading: 18:13:10.0 
Performing reading: 18:13:11.0 
Performing reading: 18:13:12.1 
Performing reading: 18:13:13.0 
Performing reading: 18:13:13.999 
Performing reading: 18:13:15.0 
Performing reading: 18:13:16.0 
Performing reading: 18:13:16.999 
Performing reading: 18:13:18.0 
Performing reading: 18:13:19.1 
Performing reading: 18:13:20.0 
Performing reading: 18:13:21.0 
Performing reading: 18:13:21.999 
Performing reading: 18:13:23.0 
Performing reading: 18:13:24.0 
Performing reading: 18:13:25.0 
Performing reading: 18:13:26.0 
Performing reading: 18:13:27.0 
Performing reading: 18:13:28.0 
Performing reading: 18:13:29.0 
+0

有了這個編輯我得到以下幾點: 表演閱讀:0:17:21.3 表演閱讀:0:17:21.183 表演閱讀:0:17:21.370 表演閱讀:0:17:21.560 表演閱讀:0 :17:21.746 進行讀出:0:17:22.187 進行讀出:0:17:22.611 進行讀出:0:17:23.267 進行讀出:0:17:23.57 進行讀出:0:17:23.314 執行閱讀:0:17:23.314 – Androme

+0

對不起,我改了幾次 - 你使用我放在那裏的最新版本的代碼(其中函數名爲GetTimeToNextSecond)? –

+0

是的,我用目前的版本 – Androme

1

使用CodingBarfield的響應,前段時間對我很好。

Raise event in high resolution interval/timer

對不起,沒有給予更多的細節,是很好的解釋出現。

+0

可能想檢查System.Threading.Timer,因爲我認爲這是圍繞引用您的引用的答案使用。 – Andy