unit AsyncTimer; { Timer like thread that will call a specific notifyevent routiner every specified interval } {$mode delphi} interface uses Classes, SysUtils, syncobjs; type TAsyncTimer=class(tthread) private fInterval: integer; fOnTimer: TNotifyEvent; fOnTimerCS: TCriticalSection; fEnabled: boolean; eenabled: TEvent; timerevent: TEvent; triggeronce: boolean; procedure setOnTimer(f: TNotifyEvent); procedure setEnabled(state: boolean); procedure setInterval(interval: integer); public procedure Terminate; procedure execute; override; procedure TriggerNow; //triggers the event constructor create(suspended: boolean); destructor destroy; override; property OnTimer: TnotifyEvent read fOnTimer write setOnTimer; property Interval: integer read fInterval write setInterval; property Enabled: boolean read fEnabled write setEnabled; end; implementation procedure TAsyncTimer.setEnabled(state: boolean); begin if state then eenabled.SetEvent else eenabled.ResetEvent; fEnabled:=state; end; procedure TAsyncTimer.setInterval(interval: integer); begin finterval:=interval; timerevent.SetEvent; //if the timer was sleeping end; procedure TAsyncTimer.setOnTimer(f: TNotifyEvent); begin fOnTimerCS.Enter; fOnTimer:=f; fOnTimerCS.Leave; end; procedure TAsyncTimer.Terminate; begin setOnTimer(nil); inherited Terminate; timerevent.SetEvent; Enabled:=true; end; procedure TAsyncTimer.TriggerNow; //triggers the event as soon as possible begin triggeronce:=true; timerevent.SetEvent; end; procedure TAsyncTimer.execute; var f: TNotifyEvent; begin while not terminated do begin while (not terminated) and (eenabled.WaitFor(INFINITE)=wrTimeout) do ; while (not terminated) and (timerevent.WaitFor(fInterval)=wrSignaled) and (not triggeronce) do //each time the interval changes this will get signaled. When that happens, wait again timerevent.ResetEvent; triggeronce:=false; if not terminated then begin try fOnTimerCS.enter; try f:=fOnTimer; finally fOnTimerCS.leave; end; if enabled and assigned(f) then f(self); except //on unexpected exceptions don't destroy the timer end; end; end; end; constructor TAsyncTimer.create(suspended: boolean); begin timerevent:=TEvent.create(nil, true, false,''); eenabled:=TEvent.Create(nil, true, false,''); fOnTimercs:=TCriticalSection.create; fEnabled:=false; finterval:=1000; inherited create(suspended); end; destructor TAsyncTimer.destroy; begin terminate; self.WaitFor; if fOnTimerCS<>nil then fOnTimerCS.free; inherited destroy; end; end.