2016-03-08 1 views
1

Я столкнулся с проблемой, когда событие Elapsed запускается до интервала. У меня есть интервал, установленный, скажем, 10000 мс, и событие срабатывает примерно в 4500 мс. Я знаю, что этот конкретный таймер не слишком точен, но я точно знаю, что он намного точнее, чем то, что он показывает.Игнорированное событие System.Timers.Timer слишком рано

Я проверил, чтобы не было более одного таймера, вызывающего это событие. Это решение отлично работает на двух из трех окон, на которых он установлен.

Может быть проблема с версией .NET, CLR версии и т.д.

Я знаю, что есть и другие способы достижения этого, но я просто искал предложения относительно того, что может быть причиной этого, чтобы работать на всего 2 из 3 серверов.

Ниже я создаю таймер только один раз при запуске службы ..

checkTimer = new System.Timers.Timer(getSecondsLeft()); 
checkTimer.Elapsed += checkNowEvent; 
checkTimer.AutoReset = true; 
checkTimer.Enabled = true; 

Вот метод, который используется, чтобы вычислить количество миллисекунд до следующей минуты

private double getSecondsLeft() 
{ 
    DateTime now = DateTime.Now; 
    // Has a chance to trigger a few milliseconds before new minute. Added 50ms to interval 
    return ((60 - now.Second) * 1000 - now.Millisecond) + 50; 
} 

И, наконец, прошедшее время.

private void checkNowEvent(object sender, ElapsedEventArgs e) 
{ 
    try 
    { 
     // Stop timer to keep from firing this event again 
     checkTimer.Enabled = false; 

     // DOING WORK HERE 
    } 
    finally 
    { 
     // Set the interval as to tick on the start of the next minute 
     checkTimer.Interval = getSecondsLeft(); 

     // Start timer again 
     checkTimer.Enabled = true; 
    } 
} 

Я просто сделал еще несколько тестов с этим, и я добавил некоторые функции секундомера, чтобы увидеть, если интервал был на самом деле стрелять, когда предполагается, и это выглядит, как она есть. Однако, когда я вычисляю правильное количество миллисекунд на следующую минуту, НО работает так, как если бы эта реализация Таймера работала быстрее, чем системные часы ... Если это имеет смысл.

Вот код, который я использовал для этого.

private void checkNowEvent(object sender, ElapsedEventArgs e) 
    { 

     stopWatch.Stop(); 
     _Log.LogDebug(stopWatch.Elapsed.ToString()); 

     try 
     { 

      // Stop timer to keep from firing this event again 
      checkTimer.Enabled = false; 

      // DOING WORK HERE 

     } 
     catch (Exception ex) 
     { 

      // CATCHING EXCEPTIONS HERE IF ANY 

     } 
     finally 
     { 
      // Set the interval as to tick on the start of the next minute 
      checkTimer.Interval = getSecondsLeft(); 
      _Log.LogDebug(checkTimer.Interval.ToString()); 

      // Start timer again 
      checkTimer.Enabled = true; 

      stopWatch.Reset(); 
      stopWatch.Start(); 
     } 
    } 
+1

Протестировано это на моей стороне, оно тикает ровно через 00 секунд каждую минуту. Кроме того, System.Timers.Timer не очень точен, но он БОЛЬШЕ точнее, чем 5.5 секунд. –

+0

Какие версии .NET установлены на 3 машинах? Это может быть хорошим местом для начала. – Cemafor

+0

Подобный вопрос с некоторой информацией [здесь] (http://stackoverflow.com/a/2432601/5095502) – Quantic

ответ

1

Причина, по которой она срабатывает до новой минуты, связана с тем, что существует проблема с системным временем. DateTime.Now возвращает правильное количество миллисекунд до следующей минуты, но системное время движется очень медленно. Похоже, что реализация таймера работает правильно, когда я проверил секундомер. Я просто синхронизировал системное время с двумя другими рабочими ПК, но не через 5 минут, это снова пара минут.

+0

http://www.sevenforums.com/performance-maintenance/289471-system- clock-going-slow.html Это может помочь – Cemafor