计时器在德尔福

时间:2009-02-08 08:45:36

标签: delphi

考虑以下代码

Timer1 .Enabled := False;
Timer1.Interval : = 300;
For I := 1 to NumberOfTimesNeed do
Begin

   Timer1 .Enabled := False;    //  
   Timer1 .Enabled := True;     // reset the timer to 0.30 seconds

   TakesToLong     := False;
   DoSomethingThatTakesTime;    // Application.ProcessMessages is called in the procedure

   If TakesToLong = True then 
      TakeAction;
End;

procedure Timer1Timer(Sender: TObject);
begin
   TakesToLong:= True;
end;

问题:

当我禁用然后使用

启用Timer1时
Timer1.Enabled := False;
Timer1.Enabled := True;

这会重置计时器吗?

即。它会在超时之前等待0.30秒。

3 个答案:

答案 0 :(得分:19)

是的,它会的。如果之前启用了计时器,则将Enabled设置为False将调用Windows API函数KillTimer()。如果之前未启用计时器,则将Enabled设置为True将调用Windows API函数SetTimer()。

这是一个标准的习惯用语,自德尔福1时代以来一直在运作。

然而,我会以不同的方式实现您的代码:

Start := GetSystemTicks;
DoSomethingThatTakesTime;
Duration := GetSystemTicks - Start;

if Duration > 300 then
  TakeAction;

没有计时器就可以工作,而且不需要在long-taking方法中调用ProcessMessages()。 GetSystemTicks()是我在库中的一个函数,它在Windows中调用timeGetTime(),并且对Kylix实现了不同的实现(不记得如何,我很久以前就清除了该代码)。

答案 1 :(得分:1)

我建议阅读线程。长时间的行动(我不是说300毫秒很长但听起来显然可能比这更长)倾向于冻结GUI并导致应用程序不稳定。现在,您可以在其中抛出application.processmessages以保持GUI的运行,但它可以轻松地抛弃您想要的程序编码风格。

我从过道那边认为 Application.ProcessMessages 应该禁止,除非你是一个VB程序员试图用Delphi来模仿 DoEvents ,你仍然没有摆脱VB思维模式。

生成一个线程并在该线程中完成您的工作。如果想在完成后更新GUI端,请调用Synchronize以“安全”执行此操作。通过线程来回传递正在进行的状态会带来一个全新的对话,这与使用计时器控件相比有了很大的飞跃。

答案 2 :(得分:1)

还需要注意的是,计时器是系统上优先级最低的通知。因此,如果计算机正忙,这可能包括应用程序在这里工作,计时器可能不会触发很长一段时间。因此,即使计时器设置为300毫秒,也可能在TakesToLong变量设置为true之前几秒钟。