Disable Delphi TTimer during the OnTimer event

When writing a Delphi TTimer event, I often disable the timer and re-enable it at the end of the event.

If you dont do this, the OnTimer event could fire again before you have finished processing it.

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.enabled := FALSE;  // disable the timer so it wont fire while we are processing it
 
      // oh oh - user interaction.
      // The timer can fire again while the message is displayed
      // if it is not disabled
  Try
    ShowMessage ('Hello'); 
  finally
    Timer1.enabled := TRUE;  // restore the timer
 end;
end;

If you dont do that the ShowMessage window would appear multiple times like in this example

procedure TForm1.Timer1Timer(Sender: TObject);
  // timer event displaying a message
begin
  Memo1.lines.add ('OnCreate'); // debug message to show the timer is firing
  ShowMessage ('Hello'); 
end;

delphi_timer_animated

The timer re-firing before the earlier timer event has completed will only occurs in a few scenarios such as:

1) when the OnTimer code is waiting on user input such as when displaying a message
2) when the OnTimer calls Application.ProcessMessages
3) I havent tested this when using threaded code, but it might occur there as well
4) There are probably other scenarios.  Post a comment if you know of any

It does not occur when the timer is calling the sleep function or when it is simply executing a long running chunk of code without any user interaction – such as calling this rather boring but slow procedure

procedure SlowProcedure;
 // do something really slow
 // this takes 3 to 10 seconds on a 2017 PC 
var
 i : integer;
 x : integer;
begin
 for i := 1 to 500000000 do
     x := trunc(x / i);
end;

Downsides

Using this technique can result in “Timer Creep” where the timer fires slower than the duration that you defined in the Interval property.

That is due to the timer countdown being reset when you re-enable it at the end of the event.

For example, if you have a 1000 millisecond timer interval and your OnCreate event takes 200 milliseconds to run.  The timer will fire every 1200 milliseconds instead of the 1000 that you were expecting.  If that is an issue for you, you could use a lower Interval value or capture the start and finish time in the OnTimer event and adjust the interval based on the original interval adjusted for the time difference.

Error Handling

Using Try / Finally is important in this technique.  If an untrapped error occurs the timer will never fire again – Eeep !

Author – Thanks to the nudge from Linden R about the importance of Try / Finally in this technique

+1 this post

Please help get this blog listed on DelphiFeeds by +1 voting here on DelphiFeeds and also vote on BeginEnd.  Thank you

About Me

scott_hollows_201611

  • Oracle & Delphi software developer based in Perth, Western Australia
  • Australian Delphi User Group – President
  • Australian Oracle User Group – WA Committee Member
  • Available to do remote presentations to user groups on Delphi and Oracle topics
blog email linkedinlogo

Published by

3 responses to “Disable Delphi TTimer during the OnTimer event”

  1. Would that be “better” as
    timer.enabled := false;
    try
    do stuff
    finally
    timer.enabled := true;
    end;

  2. Good point Linden. Without that an untrapped error would result in the timer not firing again. Ive updated the code and added a new “Error Handling” section to point that out

  3. Well, reactivating the timer at the end of the treatment is a good idea, except when an error is triggered.
    This error depending on its type could necessitate stopping the execution of the program or doing specific stuff to address it before restarting.
    Reactivating timer while ignoring the error could make the application running unpredictable.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: