2010-03-12 3 views
10

У нас возникает следующая проблема при использовании System.Threading.Timer (.NET 2.0) из службы Windows.Таймер C#, запускаемый перед их интервалом времени

  1. Есть около 12 различных объектов таймера ..
  2. Каждого таймера имеет должное время и интервал. Это верно.
  3. Наблюдается, что через 3-4 часа таймеры начинают сигнализацию до истечения интервала. Например, если таймер должен сигнализировать в 4:59:59, он получает сигнал в 4:59:52, 7 секунд раньше.

Может кто-нибудь сказать мне, в чем причина такого поведения и каково решение для этого?

Спасибо, Сватите

ответ

0

Может быть повторно планирование сделано после операции, которая занимает несколько секунд, чтобы закончить. Или вы не контролируете это?

0

Это не может быть управление, поскольку оно зависит от скорости системы, если у вас суперкомпьютер, тогда может быть недостаточно разницы, но если у вас нормальный ПК, тогда будет разница в таймерном интервале после долгого выполнение.

Надеюсь, что это поможет.

9

Большой вопрос ... и вот причина:

«Timing» это сложная вещь, когда дело доходит до компьютеров ... Вы можете никогда полагаться на «интервал», чтобы быть совершенным. Некоторые компьютеры будут «галочкой» таймера только каждые 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 мсек? Я знаю, что вы можете потерять немного точности, но разве это не лучше, чем иметь таймер огня 1000 раз в секунду, когда вам нужны только результаты каждые 3 секунды? –

6

Объяснение Тимоти убедительно, но System.Threading.Timer уже работает таким образом. По крайней мере, в реализации Rotor он использует значение, возвращаемое GetTickCount(), чтобы вычислить, когда произойдет следующий обратный вызов. Не очень вероятно, что реальная CLR тоже это сделает, более вероятно использование CreateTimerQueueTimer(). Тем не менее, эта функция API также, вероятно, будет зависеть от внутреннего тика, увеличенного прерыванием тактового сигнала.

Проблема заключается в том, насколько хорошо внутренний тактовый тик (как возвращается GetTickCount() и Environment.TickCount) синхронизируется с абсолютным временем стены (как возвращается DateTime.Now). К сожалению, это деталь реализации HAL на вашем аппарате, уровень абстракции оборудования. Конструктор машин может предоставить пользовательский HAL, который был настроен для работы с BIOS и чипсетом.

Я бы ожидал проблем, если машина имеет два источника синхронизации, микросхему часов, которая была предназначена для отслеживания времени на стене и продолжает тикать, даже если вы отключите питание компьютера, а другая частота доступна на чипсете, который можно разделить на обеспечить прерывание тактовой частоты. Оригинальный IBM AT PC работал именно так. Часовому чипу обычно можно доверять, часы были бы сильно отключены, если это неточно. Чипсет не может, резка углов по качеству осцилляторов - это простой способ спасти копейки.

Решите свою проблему, избегая длительных периодов на вашем таймере и пересчитывая следующее время от DateTime.Now в обратном вызове.

+0

Спасибо за помощь. Повторный подсчет таймеров может решить мою проблему. Я собираюсь попробовать это. Еще раз спасибо !! –

Смежные вопросы