2015-04-18 3 views
2

В настоящее время я работаю над программой, чувствительной ко времени, где важно, чтобы я читал данные с устройства каждую секунду. В настоящее время я использую таймер для этого, однако я обнаружил, что время, равное длительности, увеличивает интервал с отметкой 1 мс pr. Это может вызвать проблемы, так как программа будет работать в течение длительного времени.System.Timers.Timer неуклонно увеличивает интервал

Read Exe Time - это срок действия кода.

Performing reading в начале каждого прошедшего события.

Как я могу гарантировать, что часы не будут увеличиваться, я могу понять, что тик может быть не на точной миллисекунде, но что я продолжаю подниматься, кажется странным. и мой код не занимает полных 1000 мс для выполнения, так что это не так. Через 16,6 минут показания будут выталкиваться целую секунду.

Read Exe Time: 574.0637 ms 
Performing reading: 22:58:39.696 
Read Exe Time: 571.9422 ms 
Performing reading: 22:58:40.697 
Read Exe Time: 595.5333 ms 
Performing reading: 22:58:41.697 
Read Exe Time: 566.2602 ms 
Performing reading: 22:58:42.698 
Read Exe Time: 568.2275 ms 
Performing reading: 22:58:43.698 
Read Exe Time: 569.7573 ms 
Performing reading: 22:58:44.700 
Read Exe Time: 561.655 ms 
Performing reading: 22:58:45.701 
Read Exe Time: 567.8385 ms 
Performing reading: 22:58:46.702 
Read Exe Time: 584.8305 ms 
Performing reading: 22:58:47.703 
Read Exe Time: 588.754 ms 
Performing reading: 22:58:48.703 
Read Exe Time: 560.8154 ms 
Performing reading: 22:58:49.704 
Read Exe Time: 567.9324 ms 
Performing reading: 22:58:50.705 
Read Exe Time: 579.1354 ms 
Performing reading: 22:58:51.706 
Read Exe Time: 563.0227 ms 
Performing reading: 22:58:52.707 
Read Exe Time: 569.557 ms 
Performing reading: 22:58:53.708 
Read Exe Time: 560.707 ms 
Performing reading: 22:58:54.708 
Read Exe Time: 574.6268 ms 
Performing reading: 22:58:55.709 
Read Exe Time: 570.4872 ms 
Performing reading: 22:58:56.710 
Read Exe Time: 574.8388 ms 
Performing reading: 22:58:57.710 
Read Exe Time: 573.2054 ms 
Performing reading: 22:58:58.710 
Read Exe Time: 578.6189 ms 
Performing reading: 22:58:59.711 
Read Exe Time: 565.7442 ms 
Performing reading: 22:59:0.711 
Read Exe Time: 564.7523 ms 
Performing reading: 22:59:1.712 
Read Exe Time: 575.8134 ms 
Performing reading: 22:59:2.713 
Read Exe Time: 570.9416 ms 
Performing reading: 22:59:3.713 
Read Exe Time: 573.1493 ms 
Performing reading: 22:59:4.714 
Read Exe Time: 570.2831 ms 
Performing reading: 22:59:5.714 
Read Exe Time: 568.2672 ms 
Performing reading: 22:59:6.715 
Read Exe Time: 586.5607 ms 
Performing reading: 22:59:7.715 
Read Exe Time: 588.0465 ms 
Performing reading: 22:59:8.715 
Read Exe Time: 574.1118 ms 
Performing reading: 22:59:9.716 

Код

private void StartMeter() 
{ 
    this.Meter.Start(); 

    this.ReadingTime = new Timer(1000); 
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
    this.ReadingTime.Start(); 
} 

    private void PerformReading(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + "." + DateTime.Now.Millisecond); 

     // Code here 
    } 

Update: Если я просто установить время до 999 мс он будет неуклонно снижаться вместо

Performing reading: 23:4:50.527 
Read Exe Time: 562.7729 ms 
Performing reading: 23:4:51.527 
Read Exe Time: 566.8178 ms 
Performing reading: 23:4:52.527 
Read Exe Time: 562.3829 ms 
Performing reading: 23:4:53.526 
Read Exe Time: 567.9165 ms 
Performing reading: 23:4:54.526 
Read Exe Time: 561.1329 ms 
Performing reading: 23:4:55.525 
Read Exe Time: 562.9359 ms 
Performing reading: 23:4:56.525 
Read Exe Time: 560.4151 ms 
Performing reading: 23:4:57.524 
Read Exe Time: 561.0302 ms 
Performing reading: 23:4:58.524 
Read Exe Time: 561.5756 ms 
Performing reading: 23:4:59.524 
Read Exe Time: 565.2936 ms 
Performing reading: 23:5:0.523 
Read Exe Time: 561.8903 ms 
Performing reading: 23:5:1.523 
Read Exe Time: 561.8768 ms 
Performing reading: 23:5:2.523 
Read Exe Time: 562.3904 ms 
Performing reading: 23:5:3.523 
Read Exe Time: 562.3363 ms 
Performing reading: 23:5:4.523 
Read Exe Time: 561.6288 ms 
Performing reading: 23:5:5.523 
Read Exe Time: 560.4596 ms 
Performing reading: 23:5:6.522 
Read Exe Time: 562.34 ms 
Performing reading: 23:5:7.522 
Read Exe Time: 561.5994 ms 
Performing reading: 23:5:8.522 
Read Exe Time: 561.6811 ms 
Performing reading: 23:5:9.521 
Read Exe Time: 561.7427 ms 
Performing reading: 23:5:10.521 
Read Exe Time: 561.8044 ms 
Performing reading: 23:5:11.520 
Read Exe Time: 561.6246 ms 
Performing reading: 23:5:12.520 
Read Exe Time: 560.5753 ms 
Performing reading: 23:5:13.520 
Read Exe Time: 563.8604 ms 
Performing reading: 23:5:14.520 
Read Exe Time: 562.2606 ms 
Performing reading: 23:5:15.534 
Read Exe Time: 560.8377 ms 
Performing reading: 23:5:16.534 
Read Exe Time: 560.4553 ms 
Performing reading: 23:5:17.534 
Read Exe Time: 562.5534 ms 
Performing reading: 23:5:18.533 
Read Exe Time: 563.0269 ms 
Performing reading: 23:5:19.532 
Read Exe Time: 561.2851 ms 
Performing reading: 23:5:20.532 
Read Exe Time: 560.3442 ms 
Performing reading: 23:5:21.531 
Read Exe Time: 561.5201 ms 
Performing reading: 23:5:22.530 
Read Exe Time: 560.609 ms 
Performing reading: 23:5:23.530 

Edit: Для @PeterLuu

Performing reading: 22:44:45.13 
Performing reading: 22:44:45.449 
Performing reading: 22:44:45.879 
Performing reading: 22:44:46.320 
Performing reading: 22:44:46.761 
Performing reading: 22:44:47.192 
Performing reading: 22:44:47.631 
Performing reading: 22:44:48.74 
Performing reading: 22:44:48.577 
Performing reading: 22:44:49.49 
Performing reading: 22:44:49.637 

И код

private void StartMeter() 
{ 
    DateTime now = DateTime.UtcNow; 
    NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind); 

    this.Meter.Start(); 

    this.ReadingTime = new Timer(1000); 
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
    this.ReadingTime.Start(); 
    ReadingTime.Interval = GetTimeToNextSecond(); 
} 

private double GetTimeToNextSecond() 
{ 
    NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1); 
    var interval = NextTickTimeWholeSeconds - DateTime.UtcNow; 
    return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds; 
} 

private void PerformReading(object sender, ElapsedEventArgs e) 
{ 
    Console.WriteLine("Performing reading: " + DateTime.UtcNow.Hour + ":" + DateTime.UtcNow.Minute + ":" + DateTime.UtcNow.Second + "." + DateTime.UtcNow.Millisecond); 

    // My code takes about 500-600 ms 

    ReadingTime.Interval = GetTimeToNextSecond(); 
} 
+0

«_The время установившегося увеличивается интервал с 1 мс пр tick_» Может быть, я неправильно понял, но это звучит, что интервал не увеличивается или уменьшается, то только о ' 1.001' или '0.999's. – AlexD

+0

Да, это правильно или 1.0000-1.0001 может быть вернее – Androme

+0

Возможно, вы захотите [таймер с более высоким разрешением] (http://stackoverflow.com/questions/7137121/c-sharp-high-resolution-timer). И, возможно, придется прибегать к использованию вызовов com. –

ответ

2

Вы можете установить его на время до следующей секунды (например, если на точку будет только 890 миллисекунд до следующей секунды) и перезапустить таймер с этим интервалом на каждую итерацию, чтобы предотвратить дрейф. Адаптировано из предыдущего ответа Джареда here. Это не обеспечивает точность до миллисекунды, но это предотвратит дрейф вашего времени, и событие всегда будет срабатывать «на точку».

Редактировать: Удалена ненужная строка. На самом деле вам не нужно дважды называть Start(), достаточно просто изменить интервал, так как изменение интервала перезапускает таймер.

Редактирование 2: Сделаны некоторые изменения, чтобы сделать его более точным в кромках (например, предотвратите стрельбу несколько раз подряд).

public class Meter 
{ 
    private Timer ReadingTime; 
    private DateTime NextTickTimeWholeSeconds; 

    public Meter() { 
     DateTime now = DateTime.UtcNow; 
     NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind); 

     ReadingTime = new Timer(); 
     ReadingTime.AutoReset = false; 
     ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading); 
     ReadingTime.Interval = GetTimeToNextSecond(); 
    } 

    public void StartMeter() 
    { 
     ReadingTime.Start(); 
    } 

    private double GetTimeToNextSecond() 
    { 
     NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1); 
     var interval = NextTickTimeWholeSeconds - DateTime.UtcNow; 
     return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds; 
    } 

    private void PerformReading(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + "." + DateTime.Now.Millisecond); 
     ReadingTime.Interval = GetTimeToNextSecond(); 
    } 
} 

Результат:

Performing reading: 18:11:47.10 
Performing reading: 18:11:48.4 
Performing reading: 18:11:49.10 
Performing reading: 18:11:50.6 
Performing reading: 18:11:51.9 
Performing reading: 18:11:52.5 
Performing reading: 18:11:53.10 
Performing reading: 18:11:54.5 
Performing reading: 18:11:55.9 
Performing reading: 18:11:56.7 
Performing reading: 18:11:57.7 
Performing reading: 18:11:58.7 
Performing reading: 18:11:59.7 
Performing reading: 18:12:0.8 
Performing reading: 18:12:1.7 
Performing reading: 18:12:2.6 

... about 50 seconds later ... 

Performing reading: 18:12:50.1 
Performing reading: 18:12:51.0 
Performing reading: 18:12:52.0 
Performing reading: 18:12:53.0 
Performing reading: 18:12:53.999 
Performing reading: 18:12:55.0 
Performing reading: 18:12:56.0 
Performing reading: 18:12:56.999 
Performing reading: 18:12:58.0 
Performing reading: 18:12:59.0 
Performing reading: 18:13:0.0 
Performing reading: 18:13:0.999 
Performing reading: 18:13:2.0 
Performing reading: 18:13:3.1 
Performing reading: 18:13:4.0 
Performing reading: 18:13:5.0 
Performing reading: 18:13:6.0 
Performing reading: 18:13:6.999 
Performing reading: 18:13:8.0 
Performing reading: 18:13:9.0 
Performing reading: 18:13:10.0 
Performing reading: 18:13:11.0 
Performing reading: 18:13:12.1 
Performing reading: 18:13:13.0 
Performing reading: 18:13:13.999 
Performing reading: 18:13:15.0 
Performing reading: 18:13:16.0 
Performing reading: 18:13:16.999 
Performing reading: 18:13:18.0 
Performing reading: 18:13:19.1 
Performing reading: 18:13:20.0 
Performing reading: 18:13:21.0 
Performing reading: 18:13:21.999 
Performing reading: 18:13:23.0 
Performing reading: 18:13:24.0 
Performing reading: 18:13:25.0 
Performing reading: 18:13:26.0 
Performing reading: 18:13:27.0 
Performing reading: 18:13:28.0 
Performing reading: 18:13:29.0 
+0

С этой редактирования я получаю следующее: Выполнение чтения: 0: 17: 21,3 Выполнение чтения: 0: 17: 21,183 Выполнение чтения: 0: 17: 21,370 Выполнение чтения: 0: 17: 21,560 Выполнение чтения: 0 : 17: 21,746 Выполнение чтения: 0: 17: 22,187 Выполнение чтения: 0: 17: 22,611 Выполнение чтения: 0: 17: 23,267 Выполнение чтения: 0: 17: 23,57 Выполнение чтения: 0: 17: 23,314 Выполнение чтения: 0: 17: 23.314 – Androme

+0

Извините, я несколько раз менял его - используете ли вы код в самой последней версии, которую я там установил (где функция называется GetTimeToNextSecond)? –

+0

Да, я использовал текущую версию – Androme

1

Использование ответа CodingBarfield очень сработало для меня некоторое время назад.

Raise event in high resolution interval/timer

Извините за не давая больше деталей, красиво объяснено там.

+0

Возможно, вы хотите проверить System.Threading.Timer, поскольку я думаю, что это обернуто вокруг pinvoke, на который ссылается ваш ответ. – Andy

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