What is the difference between using TTimer and using TThread
TTimer is a message-based timer. It posts WM_TIMER messages to the message queue of the thread that creates it. Your database operations are blocking that thread from processing new messages in a timely manner. Assuming your TTimer is in the main UI thread, that is why your app performance suffers. Moving the database operations into a worker thread prevents the main thread's message loop from being blocked.
The main difference between the two can be found in their class definition:
TTimer = class(TComponent)
TThread = class
While the TTimer
class extends TComponent
and is a component itself, TThread
is an abstract class which extends TObject
.
TThread
exposes static methods like TThread.Sleep
and a peculiar protected method called Execute
which must be implemented in the derived class in order to perform the desired job.
TThread
directly uses the Processes and Threads functions of the guest OS.
... for this purpose I use
TTimer
but the delay of Database response affect on my application performance
The reason why this happens is because the OnTimer
event of the TTimer
object is executed in the calling thread: when a TTimer
component is put into a form and its OnTimer
event is implemented, the code is executed in the main thread.
The TThread
approach is more flexible: if for some reason the code must be performed in the main thread, this can be achieved nesting a sinchronized block inside the thread's Execute
method.
If you want to execute database requests in a repeated manner after some time interval, you better consider using a TThread
in combination with a TEvent
object.
An example of class definition using TEvent
:
TMyThread = class(TThread)
private
FInterval: Integer;
FWaitEvent: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create(Interval: Cardinal; CreateSuspended: Boolean);
destructor Destroy; override;
end;
The implemented class:
constructor TMyThread.Create(Interval: Cardinal; CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FInterval := Interval;
FWaitEvent := TEvent.Create(nil, False, False, '');
end;
destructor TMyThread.Destroy;
begin
FWaitEvent.Free;
inherited;
end;
procedure TMyThread.TerminatedSet;
begin
inherited;
FWaitEvent.SetEvent;
end;
procedure TMyThread.Execute;
begin
inherited;
while not Terminated do begin
//do your stuff
//wait fo some amount of time before continue the execution
if wrSignaled = FWaitEvent.WaitFor(FInterval) then
Break;
end;
end;
The WaitFor
method called on the FWaitEvent
object allows to wait for the desired amount of time.
The implementation of the thread's TerminatedSet
method allows to put the FWaitEvent
object in a signaled state and then exit from the thread before the interval has elapsed.
This doesn't specifically address your q, but as noted in a comment to one of the other answers, polling a database at the frequency you're doing isn't a good idea, especially if other users are trying to access it.
There are various ways to get notifications from database servers when data changes, without needing to continually poll them. This Embarcadero paper has a very useful review of what's available for various DBMSs:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Database_Alerts_%28FireDAC%29
If your Delphi version includes FireDAC, as you'll see from the link that you could use TFDEventAlerter to receive notifications of data changes on the server if your DBMS supports it.
If you're using Interbase or Firebird (and maybe some others), there are alternate Delphi components available that don't require FireDAC, e.g. TIBEventAlerter in the IBExpress ibrary for Interbase.