There is a program that at a specified time, on a timer, copies files. The copy time value is specified in the DateTimePicker (displays only time).

The time value from the DateTimePicker is written to the ScheduledTime variable, then it is compared with DateTime.Now, and if the ScheduledTime value is less, then 1 day is added. GetSetScheduledTime () function:

if (DateTime.Now > ScheduledTime) { while (DateTime.Now >= ScheduledTime) { ScheduledTime = ScheduledTime.AddDays(1); DateTimePickerTimer.Value = DateTimePickerTimer.Value.AddDays(1); } } 

The while loop is used to read the date from the config file, where the date may be old.

After refining ScheduledTime, we get the TickTime interval for the timer:

  TickTime = (int)(GetSetScheduledTime() - DateTime.Now).TotalMilliseconds; if (TickTime >= 0) { TimerPl.Interval = TickTime; //Start Main Timer TimerPl.Start(); } 

After the timer is triggered, the TimerTick function stops the timer, starts the copy function, sends reports and logs and starts the timer function again, checks the time, turns out a new interval, and waits for the next trigger again.

The problem is that time floats. On the first day, on 2 different computers, the timer worked exactly, on the second day, it worked earlier for 1 second and 2 seconds. Whether this time will increase is not yet clear.

I understand that the timer is not an exact tool and tics can be delayed or go faster. But if we have a value from the DateTimePicker, where the time does not change, it only increases by 1 day and then this value is assigned to ScheduledTime and if every time I get a new interval that is equal to the planning time, the current time, should the error accumulate or can? How to avoid it? I do not mind backlash up to 5 seconds, but if this value will constantly increase, how to adjust the time?

UPD: In short, it was not possible to achieve the exact time, but since the task never stood, I have a backlash per second. I take this into account when forming the next date, reset all values ​​where necessary and everything works. Sharp timers are not the best solution where you need accurate time. If possible, try to avoid them.

  • How do you decide that the problem is in the timer? Do you change the timer interval synchronously? Maybe your operations, what you do, on different machines take different time, on that and out of sync. - tym32167
  • @ tym32167 I think that the problem is in the Timer, because if it worked later, then it would be possible to write all this off to the fact that the copy function takes longer to copy on different machines. But it works before. With that, on the machine, where constantly besides this, something else is being done, it works 1 second earlier, and on another machine that just stands and does nothing - 2 seconds earlier. In general, the program works (and will work) on 1 computer. Just tested it for 2 and got a different result. - DmStk
  • You change the timer interval, which means it can be either more or less. I in your place would log everything, including the set intervals and the dates / times of their setting + would prepare a minimal reproducible example. The timer, of course, is not a very accurate thing, but 2 seconds of discrepancy per day and 2 starts is a bust - tym32167
  • one
    Use the Windows Scheduler for this purpose. - Andrey NOP
  • @ AndreiNOP Well, so far I do not see a great point in this. According to the results yesterday, the error is = - 1 second from the timer. It does not matter to me that it runs exactly on time. Just because of the floating time, while there was no processing and checks, an error fell out. Now corrected it. But globally, the problem with timers, I see there is at all. and I did not find adequate solutions anywhere. Therefore, he asked. - DmStk

1 answer 1

The question is with the accuracy of the timer, for this situation, I decided so. I have a DateTimePicker on the form, which when the program starts (if there is no saved data in the config), DateTime.Today is initialized - i.e. today, 00:00:00. There is a function:

  DateTime GetSetScheduledTime() { //Получаем время из DateTimePicker - дата меня не интересует ScheduledTime = DateTimePickerTimer.Value; //Первая проверка. Если текущее время больше ScheduledTime то добавлять день\дни if (DateTime.Now > ScheduledTime) { //Проверить Scheduled Date и добавить день или дни, если в конфиге старая дата while (DateTime.Now >= ScheduledTime) { ScheduledTime = ScheduledTime.AddDays(1); DateTimePickerTimer.Value = DateTimePickerTimer.Value.AddDays(1); } } //Вторая проверка. Если текущее время +-5 секунд больше ScheduledTime if (DateTime.Now.AddSeconds(5) > ScheduledTime || DateTime.Now.AddSeconds(-5) > ScheduledTime) { ScheduledTime = ScheduledTime.AddDays(1); DateTimePickerTimer.Value = DateTimePickerTimer.Value.AddDays(1); } //Если таймер установлен на 00:00:00 то добавить 1 день. if (ScheduledTime == DateTime.Today) { ScheduledTime = ScheduledTime.AddDays(1); DateTimePickerTimer.Value = DateTimePickerTimer.Value.AddDays(1); } return ScheduledTime; } 

In it, as you can see there are 3 checks. Further, this function is called in Start Timer:

 void TimerStart() { try { GetSetScheduledTime(); //Milliseconds Value to Main Timer TickTime = (int)(GetSetScheduledTime() - DateTime.Now).TotalMilliseconds; if (TickTime >= 0) { TimerPl.Interval = TickTime; //Start Main Timer TimerPl.Start(); } else { //Wait 5 seconds System.Threading.Thread.Sleep(5000); GetSetScheduledTime(); TickTime = (int)(GetSetScheduledTime() - DateTime.Now).TotalMilliseconds; if (TickTime >= 0){ TimerPl.Interval = TickTime; TimerPl.Start(); } else { //выбросить исключение } } } catch (System.ArgumentOutOfRangeException ex) { TimerPl.Stop(); //Отправляем логи и т.д. } } 

With timer tick, I stop the timer, start the copy function, call GetSetScheduledTime again in it, send mail and logs. I start the timer and everything goes on a new one. Slightly reduced the code that would not have turned a sheet. In this version, everything works. The timer starts a second earlier, but this is not so important. I do not need the exact time. I need it to copy. And if there are problems, then reports go to the post office and there is enough time to go remotely and do everything. Since it is copied from a dozen text files, the copy function flies very quickly. For other cases, this option is not a fact that the rules will work. I understand that the code is primitive, but this is what happened to write after more than 2 years break.