unit uMyTimer; interface uses System.Classes, System.SyncObjs, System.SysUtils; type TTimerExec = procedure(Sender: TObject; const txt: string; o: Boolean) of object; TMyTimerThread = class(TThread) private FEvent: TEvent; FCriticalSection: TCriticalSection; FInterval: Integer; FText: string; FFlagO: Boolean; FEnabled: Boolean; FOnTimerExec: TTimerExec; procedure SyncTimerEvent; protected procedure Execute; override; public constructor Create(AIntervalMinutes: Integer; const AText: string; AFlagO: Boolean); destructor Destroy; override; procedure StartT; procedure StopT; procedure TerminateAndDestroy; procedure Update(AIntervalMinutes: Integer; const AText: string; AFlagO: Boolean); property OnTimerExec: TTimerExec read FOnTimerExec write FOnTimerExec; end; implementation { TMyTimerThread } constructor TMyTimerThread.Create(AIntervalMinutes: Integer; const AText: string; AFlagO: Boolean); begin inherited Create(True); FreeOnTerminate := False; FEvent := TEvent.Create(nil, True, False, ''); FCriticalSection := TCriticalSection.Create; FInterval := AIntervalMinutes * 60 * 1000; FText := AText; FFlagO := AFlagO; FEnabled := False; end; destructor TMyTimerThread.Destroy; begin StopT; Terminate; FEvent.SetEvent; if not Suspended then WaitFor; FreeAndNil(FEvent); FreeAndNil(FCriticalSection); inherited; end; procedure TMyTimerThread.Execute; var WaitResult: TWaitResult; LocalInterval: Integer; begin while not Terminated do begin FCriticalSection.Enter; try if FEnabled then LocalInterval := FInterval else LocalInterval := INFINITE; finally FCriticalSection.Leave; end; WaitResult := FEvent.WaitFor(LocalInterval); FCriticalSection.Enter; try if FEnabled and (WaitResult = wrTimeout) then begin if Assigned(FOnTimerExec) then SyncTimerEvent; end; finally FCriticalSection.Leave; end; FEvent.ResetEvent; end; end; procedure TMyTimerThread.StartT; begin FCriticalSection.Enter; try FEnabled := True; Suspended:=false; finally FCriticalSection.Leave; end; if Suspended then Start; FEvent.SetEvent; end; procedure TMyTimerThread.StopT; begin FCriticalSection.Enter; try FEnabled := False; Suspended:=true; finally FCriticalSection.Leave; end; FEvent.SetEvent; end; procedure TMyTimerThread.SyncTimerEvent; var LText: string; LFlag: Boolean; begin FCriticalSection.Enter; try LText := FText; LFlag := FFlagO; finally FCriticalSection.Leave; end; if Assigned(FOnTimerExec) then FOnTimerExec(Self, LText, LFlag); end; procedure TMyTimerThread.TerminateAndDestroy; begin StopT; Terminate; Free; end; procedure TMyTimerThread.Update(AIntervalMinutes: Integer; const AText: string; AFlagO: Boolean); begin FCriticalSection.Enter; try FInterval := AIntervalMinutes * 60 * 1000; FText := AText; FFlagO := AFlagO; finally FCriticalSection.Leave; end; FEvent.SetEvent; end; end.