tags:

views:

1620

answers:

3

Consider the following code

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;

Question :

When I disable and then enable the Timer1 with

Timer1.Enabled := False;
Timer1.Enabled := True;

Does this reset the timer ?

i.e. will it always wait 0.30 Seconds before timing out.

+11  A: 

Yes, it will. Setting Enabled to False will call the Windows API function KillTimer() if the timer was enabled before. Setting Enabled to True will call the Windows API function SetTimer() if the timer was not enabled before.

It's a standard idiom, which has been working since the times of Delphi 1.

I would however implement your code in a different way:

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

if Duration > 300 then
  TakeAction;

which would work without a timer, and without the need to call ProcessMessages() in the long-taking method. GetSystemTicks() is a function I have in a library, which does call timeGetTime() in Windows, and which was implemented differently for Kylix (don't remember how, I purged that code long ago).

mghie
Great answer and even better suggestion!
Gamecat
@mghie I have changed the code to use GetSystemTicks and it works well thanks :)
Charles Faiga
A: 

I would suggest reading up on threads. Long actions (I'm not saying 300 ms is long but it sounds like that it could obviously go longer than that) tend to freeze the GUI and lead to choppy applications. Now, you can throw application.processmessages in there to keep the GUI going, but it can easily throw off your intended procedural coding style.

I'm from the side of the aisle that believes Application.ProcessMessages should be banned unless you are a VB programmer trying to use Delphi to mimic DoEvents and you still haven't gotten out of the VB mindset.

Spawn a thread and do your work in that thread. If want to update the GUI side when you are done, call Synchronize to 'safely' do so. Communicating the ongoing status back and forth with the thread brings in a whole new conversation that is quite a leap from using the timer control though.

Darian Miller
While I think that threads are a great thing, using them will equally "throw off your intended procedural coding style" (BTW, I agree with that observation, I'm just pointing it out). The GUI has to be handled in the same way to prevent the calling of non-reentrant code.
mghie
+1  A: 

One further thing to be aware of is that timers are the lowest priority notification on the system. So if the computer is busy, which may include the app here doing its work, the timer may not trigger for quite a while. So it could be several seconds before the TakesToLong variable gets set to true, even though the timer is set to 300 milliseconds.

mj2008