0
votes

I made a small stopwatch as a learning project a few years ago using the following code:

private: System::Windows::Forms::Timer^  timer1;
...    
this->timer1->Interval = 10;

this->timer1->Tick += gcnew System::EventHandler(this, &Form1::timer1_Tick);
...
intCentiSeconds= 0;
intSeconds = 0;
intMinutes = 0;
intHours = 0;
...
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {

 intCentiSeconds++;
 if(intCentiSeconds==100){
     intCentiSeconds = 0;
     intSeconds++;
 }
 if(intSeconds==60){
     intSeconds = 0;
     intMinutes++;
 }
 if(intMinutes==60){
     intMinutes = 0;
     intHours++;
 }
...

Haven't paid it any mind until yesterday when I tried to check my heart rate with it and was shocked to see how high it was. After a bit of fumbling to figure out why my heart was so unusually fast, I ended up testing my "stopwatch" against Windows' clock and my phone's stopwatch and it turns out that the code above resulted in a very slow timer: counts to 1 minute in about 1'30".

After a bit of digging, I found that

Windows Forms Timer component is single-threaded, and is limited to an accuracy of 55 milliseconds

and I thought I had my answer, so I figured I could use tenths of a second for the ticks (this->timer1->Interval = 10;) and recompile. Accuracy improved, but it was still quite slow. Finally, I got rid of all subseconds measurements, and again accuracy improved, but it's still off by 5 seconds over 5 minutes.

Using a more accurate timer like System::Timers::Timer would probably fix the issue, but I don't particularly care about this stopwatch, it was just a learning project from way back when.

What I would like is an explanation of what's happening here. Why is a timer supposedly accurate at 55ms is still noticeably inaccurate with a 1000 ms interval?

1

1 Answers

0
votes

This is likely due to overhead from event processing.

The timer raises an event every time it ticks. It takes time for this event to be recognized by the UI thread and processed. Additionally, if the UI thread is occupied with other tasks, this event may not be recognized immediately. In particular, if this overhead is on the order of, or larger than, the tick interval itself, you're going to have problems.

Since this overhead is incurred every time a Tick event fires, the inaccuracy compounds over time if not properly accounted for.