Search code examples
delphitimer

Calculating Intervals


In Delphi application I have used timer to do some routine checks at various time intervals like 10 secs, 5Mins, 1Hr etc. Within the timer if I use GetTickCount() to check the intervals then when machine resumes from sleep all events get triggered simultaneously. If I check intervals using the timer calls then whenever my application slows down due to machine performance or application doing heavy processing, then the timer stalls too and all my variables accumulate lag.

What is a correct approach? The accuracy is not critical, around 2 secs variation in an hour is fine.


Solution

  • I prefere some kind of "Watchdog" thread for such a task:

    TWatchdog = class(TThread)
      private
        fEvt : TSimpleEvent;
      protected
        procedure Execute; override;
      public
        procedure SigTerminate;
     
        constructor Create;
        destructor Destroy; override;
      end;
    
    implementation
    
    procedure TWatchdog.Execute;
    begin
         NameThreadForDebugging('Watchdog');
    
         while not Terminated do
         begin
              // ###########################################
              // #### Main loop - execute every 10sec
              if fEvt.WaitFor( 10000 ) = wrTimeout then
              begin
                   // ###########################################
                   // #### Main procedures (returns false in case of error)
                   if not DoTestHere then
                      break;
              end;
         end;
    end;
    
    procedure TWatchdog.SigTerminate;
    begin
         Terminate;
         fEvt.SetEvent;
    end;
    
    constructor TWatchdog.Create;
    begin
         fEvt := TSimpleEvent.Create(nil, True, False, '');
    
         // Start immediately
         inherited Create(False);
    end;
    

    It does not block your main gui code but you need to take make sure your testing code is thread save and does not address any vcl/firemonkey gui elements.

    When stopping the applicaiton just call SigTerminate and wait until the thread stops (call the threads WaitFor function).