这样,一次未执行完毕,下一次定时到,这时候程序会如何执行?
可能的情况:
1、丢弃还未执行的代码,开始新的执行;
2、不丢弃,Timer消息进入消息队列排队,等到原来的代码执行完毕后,马上开始新的执行;
3、重入,就是原来的还继续执行,同时又开始一个新的执行;
正确的是第二种。
TTimer的内部实现,是通过API函数SetTimer实现的,设置定时器以后,会定时的通过消息通知。如果OnTimer事件的处理函数耗费时间过多,超出了Timer定时以后,这些消息是排了队的等候的,所以会越积越多。但是函数会执行完毕,不可能被丢掉重入。
至于为什么在定时器中i++好像没有效果,这是因为CPU一直在忙着,没有及时更新i的值。简单例程说明:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
MessageDlg(IntToStr(i),mtInformation, TMsgDlgButtons() << mbOK, 0);
i++;
Application->ProcessMessages();
}
运行后可以看到,i的值是在变化的(当然,如果你很快的点击,还是能发现i的值变化并不规律,这还是因为线程在阻塞着)。
所以,如果在定时器的OnTimer中弹出消息框,最好是进入后先禁用定时器,出去时再启用定时器,如:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;
MessageDlg(IntToStr(i),mtInformation, TMsgDlgButtons() << mbOK, 0);
i++;
Application->ProcessMessages();
Timer1->Enabled = true;
}
顺便补充一下,当禁用时Timer1->Enabled = false,其内部是通过API函数KillTimer实现的,启用时Timer1->Enabled = true, 其实只是再次用SetTimer设置定时器而已。
用科学的方法证明,比胡乱的猜测要好。