Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi中的计时器_Delphi - Fatal编程技术网

Delphi中的计时器

Delphi中的计时器,delphi,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; DoSomethingTh

考虑以下代码

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;
问题:

当我禁用然后启用计时器1时

Timer1.Enabled := False;
Timer1.Enabled := True;
这会重置计时器吗


i、 e.在超时前,它将始终等待0.30秒

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

这是一个标准的习惯用法,从Delphi1时代起就一直有效

但是,我将以不同的方式实现您的代码:

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

if Duration > 300 then
  TakeAction;

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

我建议阅读线程。长时间的操作(我不是说300毫秒很长,但听起来很明显,它可能会比这更长)会冻结GUI并导致应用程序不稳定。现在,您可以在其中抛出application.processmessages来保持GUI的运行,但它可以很容易地摆脱您预期的过程编码风格

我来自相信应用程序的那一边。ProcessMessages应该被禁止,除非你是一个试图使用Delphi模仿DoEvents的VB程序员,而且你还没有摆脱VB思维模式


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

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

答案很好,建议也更好@MGHIE我已经改变了代码使用GETSealTICKS,它工作得很好,谢谢:)或者,考虑使用A。有一次,然后在每次循环迭代中,您可以执行您的工作(不必担心消息处理),最后使用
WaitForSingleObject()
以0毫秒的超时来查看计时器是否已过。呃,您为什么不试试呢?没有0.3秒的空闲时间?;)虽然我认为线程是一件伟大的事情,但使用它们同样会“摆脱您预期的过程编码风格”(顺便说一句,我同意这一观点,我只是指出它)。GUI必须以相同的方式处理,以防止调用不可重入代码。事实上,如果窗口消息队列为非空,则计时器消息永远不会明显“接收”,因此基本上计算机只需做一些轻微的处理工作,计时器消息可能会离开一段不确定的长时间(在我的一些应用程序中,我已经看到这种情况发生了好几个小时。)