Use the multimedia timer which is designed for this purpose. Delphi timers are awful and really only get attention during idle time. A thread-based timer is only useful when that thread gets attention. The MMTimer operates at kernel level and provides a callback that is really quite accutate. We use it for hardware sequencing automation control it is so good.
Here is my unit that implements an MMTimer as a more easy to use TTimer. Use 'Repeat' to make it single-shot or repetetive.
unit UArtMMTimer;
interface
uses
Classes,
SysUtils,
ExtCtrls,
MMSystem;
type
TArtMMTimer = class( TObject )
constructor Create;
destructor Destroy; override;
PRIVATE
FHandle : MMResult;
FRepeat : boolean;
FIntervalMS : integer;
FOnTimer : TNotifyEvent;
FEnabled : boolean;
procedure RemoveEvent;
procedure InstallEvent;
procedure DoOnCallback;
procedure SetEnabled( AState : boolean );
procedure SetIntervalMS( AValue : integer );
PUBLIC
property Enabled : boolean
read FEnabled
write SetEnabled;
property OnTimer : TNotifyEvent
read FOnTimer
write FOnTimer;
property IntervalMS : integer
read FIntervalMS
write SetIntervalMS;
end;
implementation
uses
Windows;
// TArtMMTimer
// --------------------------------------------------------------------
procedure MMTCallBack(uTimerID, uMessage: UINT;
dwUser, dw1, dw2: DWORD) stdcall;
var
Timer : TArtMMTimer;
begin
Timer := TArtMMTimer( dwUser );
Timer.DoOnCallback;
end;
constructor TArtMMTimer.Create;
begin
Inherited Create;
FIntervalMS := 100;
FRepeat := True;
end;
destructor TArtMMTimer.Destroy;
begin
FOnTimer := nil;
RemoveEvent;
Inherited Destroy;
end;
procedure TArtMMTimer.RemoveEvent;
begin
If FHandle <> 0 then
begin
timeKillEvent( FHandle );
FHandle := 0;
end;
end;
procedure TArtMMTimer.InstallEvent;
var
iFlags : integer;
begin
RemoveEvent;
If FRepeat then
iFlags := TIME_PERIODIC Or TIME_CALLBACK_FUNCTION
else
iFlags := TIME_CALLBACK_FUNCTION;
FHandle := timeSetEvent(
FIntervalMS,
0,
@MMTCallBack,
DWord(Self),
iFlags );
end;
procedure TArtMMTimer.SetEnabled( AState : boolean );
begin
If AState <> FEnabled then
begin
FEnabled := AState;
If FEnabled then
InstallEvent
else
RemoveEvent;
end;
end;
procedure TArtMMTimer.DoOnCallback;
var
NowHRCount, WaitHRCount,IntervalHRCount : THRCount;
begin
If Assigned( FOnTimer ) then
FOnTimer( Self );
end;
procedure TArtMMTimer.SetIntervalMS( AValue : integer );
begin
If AValue <> FIntervalMS then
begin
FIntervalMS := AValue;
If Enabled then
begin
Enabled := False;
Enabled := True;
end;
end;
end;
// End TArtMMTimer
// --------------------------------------------------------------------
end.