2016-05-07 8 views
2

分の1分、1:00、1:01、1:02などでタイマーを起動することはできません。代わりに、タイマーが数回秒各反復タイマーは1分に1分です

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

私はそれが1秒に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

nah完全にパッシブなコード。 – Ivan

答えて

3

TimerのみIntervalよりも速くならないことが保証されて漂います。

これを呼び出すと、1秒ごとに言って、1分をチェックする必要があります。

さらに精度を高めるには、1/2秒ごとまたはそれ以上を確認する必要があります。

情報理論の基本的な規則は、与えられた解像度(あなたの場合は1秒)で測定するには、その解像度の2倍よりも良いサンプルで行う必要があるということです。したがって、20kHzを測定するには、2x20kHz、たとえば44.1kHzよりも優れた周波数を必要とします。 (番号を認識?)

をあなたがそうしばしば単に時間の正確なポイントを取得するためにそれを呼び出すにしたくない場合は、それぞれの上にTimer.IntervalをリセットTick少しより複雑なコードを書くことができ半分の下に残りの時間は、次の完全な分まで、それは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

これは情報理論の基本的なルールであり、与えられた解像度で測定するには、その分解能の2倍よりも良いサンプルで行う必要があると言います。したがって、20kHzを測定するには、2x20kHz、たとえば44kHz以上が必要です。 (数字を認識していますか?)もちろん、ある時点を測定するだけで済む場合、これは無駄です。最適化されているがまだ単純なアルゴリズムについては私の最後の段落を見てください。 – TaW

関連する問題