Таймер C# запущен перед их временем интервала

Мы получаем следующую проблему при использовании System.Threading.Timer (.NET 2.0) от службы Windows.

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

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

Спасибо, Swati

12
задан Jon Seigel 12 March 2010 в 14:00
поделиться

4 ответа

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

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

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

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

8
ответ дан 2 December 2019 в 19:31
поделиться

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

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

0
ответ дан 2 December 2019 в 19:31
поделиться

Отличный вопрос ... и вот причина:

"Расчет времени" - непростая вещь, когда дело касается компьютеров ... вы можете никогда никогда не полагайтесь на «интервал», чтобы быть идеальным. Некоторые компьютеры будут «тикать» таймером только каждые 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 секунды.

10
ответ дан 2 December 2019 в 19:31
поделиться

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

0
ответ дан 2 December 2019 в 19:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: