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;
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;
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.
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
- 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