考虑以下代码
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秒。
答案 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之前几秒钟。