0

几年前,我使用以下代码制作了一个小型秒表作为学习项目:

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++;
 }
...

直到昨天,当我试图用它检查我的心率并震惊地看到它有多高时,我才注意到它。在摸索了一下为什么我的心跳如此之快之后,我最终测试了我的“秒表”与 Windows 的时钟和手机的秒表,结果发现上面的代码导致了一个非常慢的计时器:计数到 1大约 1'30" 分钟。

经过一番挖掘,我发现

Windows 窗体计时器组件是单线程的,并且精度限制为 55 毫秒

我想我已经有了答案,所以我想我可以用十分之一秒的时间来标记 ( this->timer1->Interval = 10;) 并重新编译。准确度提高了,但还是很慢。最后,我摆脱了所有亚秒级测量,再次提高了准确性,但在 5 分钟内仍然相差 5 秒。

使用像 System::Timers::Timer 这样更准确的计时器可能会解决这个问题,但我并不特别关心这个秒表,它只是一个很久以前的学习项目。

我想要的是对这里发生的事情的解释。为什么在 55 毫秒时应该准确的计时器在 1000 毫秒间隔时仍然明显不准确?

4

1 回答 1

0

这可能是由于事件处理的开销。

计时器每次计时都会引发一个事件。UI 线程识别并处理此事件需要时间。此外,如果 UI 线程被其他任务占用,则可能无法立即识别此事件。特别是,如果这种开销大约等于或大于滴答间隔本身,那么您将遇到问题。

由于每次触发 Tick 事件时都会产生此开销,因此如果没有正确考虑,不准确性会随着时间的推移而加剧。

于 2013-10-25T07:53:40.750 回答