Таймеры .NET, они запускаются с точным интервалом или после обработки + интервал - PullRequest
4 голосов
/ 28 августа 2011

Итак, достаточно простой вопрос.

Как именно работает интервал для System.Timers?

Запускается ли оно 1 секунду каждую секунду, независимо от того, сколько времени занимает событие тайм-аута или требуется, чтобы процедура сначала завершилась, а затем перезапустила интервал?

Так что либо:

  1. 1 сек .... 1 сек .... 1 сек и т. Д.
  2. 1 сек + время обработки .... 1 сек + время обработки .... 1 сек + время обработки и т. Д.

Причина, по которой я спрашиваю это, состоит в том, что я знаю, что моя «обработка» занимает намного меньше 1 секунды, но я хотел бы запускать ее каждую секунду на точке (или как можно ближе).

Я использовал метод Thread.Sleep примерно так:

Thread.Sleep(1000 - ((int)(DateTime.Now.Subtract(start).TotalMilliseconds) >= 1000 ? 0 : (int)(DateTime.Now.Subtract(start).TotalMilliseconds)));

Где время начала регистрируется в начале процедуры. Проблема здесь в том, что Thread.Sleep работает только в миллисекундах . Таким образом, моя подпрограмма может перезапуститься с 1000 мсек или долей более 1000.0234 мсек, что может произойти, поскольку одна из моих подпрограмм занимает 0 мсек согласно «TimeSpan», но, очевидно, она использует тики / наносекунды - что будет означать, что время выключено и не будет дольше каждую секунду. Если бы я мог спать в тиках или наносекундах, это было бы ударом.

Если номер 1 относится к System.Timers, то я думаю, что я отсортирован. Если нет, мне нужен какой-нибудь способ «уснуть» нить с более высоким разрешением времени, т.е. тики / наносекунды.

Вы можете спросить, почему я делаю встроенное выражение IF, иногда обработка может превышать 1000 мс, поэтому нам нужно убедиться, что мы не создаем минус. Кроме того, к тому времени, когда мы определим это, время окончания немного изменилось - ненамного, но это может сделать задержку потока немного более длительной, вызывая весь последующий спящий режим.

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

Обновление 1

Ok. Поэтому я не осознавал, что вы можете ввести TimeSpan в качестве значения времени. Поэтому я использовал следующий код:

Thread.Sleep(TimeSpan.FromMilliseconds(1000) - ((DateTime.Now.Subtract(start).TotalMilliseconds >= 1000) ? TimeSpan.FromMilliseconds(0) : DateTime.Now.Subtract(start)));

Если я прав, это должно позволить мне повторить нить ровно через 1 секунду - или настолько близко, насколько позволит система.

1 Ответ

2 голосов
/ 28 августа 2011

Если вы установили AutoReset = true;, тогда ваша теория 1 верна, в противном случае вам пришлось бы иметь дело с этим в коде - см. документацию для Timer в MSDN .

...