2016-05-07 160 views
2

我不能讓計時器在一分鐘,一點,一點,一點,一點二分鐘等一次點火。相反,當計時器執行一些漂移秒每次迭代計時器每分鐘一分鐘

internal void StartTimer() 
    { 
     DateTime nowEastern = CalendarEntity.Calendar.GetEasternTime(); 

     int secondsInterval = 5; 

     double additionalSeconds = secondsInterval - nowEastern.TimeOfDay.TotalSeconds % secondsInterval; 
     if (additionalSeconds == 0) 
     { 
      additionalSeconds = 1; 
     } 
     var nearestOnOneMinutes = new DateTime(
      nowEastern.Year, 
      nowEastern.Month, 
      nowEastern.Day, 
      nowEastern.Hour, 
      nowEastern.Minute, 
      nowEastern.Second 
     ).AddSeconds(additionalSeconds); 

     TimeSpan timeToStart = nearestOnOneMinutes.Subtract(nowEastern); 
     TimeSpan tolerance = TimeSpan.FromSeconds(1); 
     if (timeToStart < tolerance) 
     { 
      timeToStart = TimeSpan.Zero; 
     } 

     timer_onem = new System.Threading.Timer(OnTimedEvent, null, 
            (int)timeToStart.TotalMilliseconds, Timeout.Infinite); 
    } 

    private static void OnTimedEvent(object o) 
    { 
     var minute = DateTime.Now.Minute; 
     var second = DateTime.Now.Second; 
     if (minute != lastMinute && second % 60 < 2) 
     { 
      lastMinute = minute; 
      CodeToExecute(); 
     } 
    } 

    static void CodeToExecute() 
    { 
     double tms = 60000; 

     // code here 
     int wait = 60 - System.DateTime.Now.Second; 

     timer_onem.Change(Convert.ToInt64(tms) - wait, Timeout.Infinite); 
    } 

EDIT 1

我改變的時間間隔,以便它觸發一次的第二和然後檢查分鐘已經改變。不過漂移

timer_onem = new System.Threading.Timer(OnTimedEvent, null, 
            (int)timeToStart.TotalMilliseconds, 1000); 

    private static void OnTimedEvent(object o) 
    { 
     var minute = DateTime.Now.Minute; 

     if (minute != lastMinute) 
     { 
      lastMinute = minute; 
      CodeToExecute(); 
     } 
    } 

    private static void CodeToExecute() 
    { 
     if (bGenerate) 
     { 
      double tms = 1000; 
      // code 
      timer_onem.Change(Convert.ToInt64(tms), 1000); 
     } 
    } 
+0

是你執行創造了很多的工作量的代碼?如果是這樣,你應該把它移到後臺工作人員。 – TaW

+1

完全無源代碼。 – Ivan

回答

3

一個Timer保證是沒有更快Interval

所以你需要調用它,說每秒鐘,並檢查整個分鐘。

爲了獲得更好的精度,您必須檢查每1/2秒或更好。

這是信息論的基本原則,它說以一個給定的分辨率(在你的案例中爲1秒)來衡量,你需要以比分辨率高兩倍的速度進行採樣。因此,要測量20kHz,你需要一個比2x20kHz更好的掃描速率,比如說44.1kHz。 (這些號碼識別?)

如果你不想把它叫做這麼經常爲僅僅讓一個精確的時間點,你可以寫一個稍微複雜些的代碼,每個Tick重置Timer.Interval做有一點下半部分的剩餘時間直到下一個完整分鐘,直到它說500ms ..

雖然在你的代碼中有相當複雜的事情來設置預期的時間,確保它們不是真正的問題。應該從定時器的缺乏精度增長漂移,除非你收集'錯誤..

+0

請參閱編輯1.似乎無助於增加定時事件的頻率。 – Ivan

+0

你是說爲了讓我在+/- 1秒漂移(或60000毫秒)的整數分鐘邊界上執行一些操作,我必須每隔500毫秒就有一次定時器啓動一次?這似乎是荒謬的。所以1:01:01,1:02:02,1:03:02,1:04:01都可以,但是我得到1:01:02,1:02:04,1:03:06等等秒數單調遞增。 – Ivan

+0

那麼這是信息論的基本規則,並且說要以給定的分辨率進行測量,您需要以比分辨率高兩倍的速度進行採樣。因此,要測量20kHz,你需要比2x20kHz更好,比如44kHz。 (識別數字?)當然,如果你只需要測量一個時間點,這是浪費的;請參閱我的最後一段,瞭解優化但仍然簡單的算法。 – TaW