I just learned that creating and using a Vcl.TTimer
from a worker thread is not thread safe. My worker thread works fine ‘most of the time’ using the Vcl.TTimer
. I found a class TTimerThread
based on events which works fine also, but I don’t know how to combine both classes that TTimerThread
has access to the methods of my worker thread.
ExecuteTimed()
will be called when the event occurs (3000ms).
Pseudo code:
uses TimerThread;
type
TMyTimerThread = class( TTimerThread )
protected
procedure ExecuteTimed; override;
[...]
TMQTTClient = class(TThread)
private
[...]
fKeepAliveTimer:TTimer; // Works, but is ugly.
fKeepAliveTimerThread:TMyTimerThread; //
[...]
procedure TMyTimerThread.ExecuteTimed;
begin
beep; // Works fine!
end;
[...]
constructor TMQTTClient.Create(aHostname: string; aPort: integer; ClientID:String;aKeepAliveSeconds : word);
begin
//init some stuff...
fKeepAliveTimer:=TTimer.Create(nil); // ugly
fKeepAliveTimer.Interval:=fKeepAliveSeconds * 1000;
fKeepAliveTimer.OnTimer:=DoKeepAlive; // The function pointer which should be called ~ every xxxx ms. Works fine, but no thread safe.
fKeepAliveTimerThread:=TMyTimerThread.Create();
fKeepAliveTimerThread.Interval:=3000;
//fKeepAliveTimerThread.ExecuteTimed := ?; //here I wish to assign a pointer to the ExecuteTimed method of MyTimerThread.
I could imagine solving it using TThread.Synchronize()
in ExecuteTimed()
which calls the instance of the worker thread like frmMain.myMqttWorkerClass.DoKeepAlive
, but I am in doubt if this is the right way.
Sascha Ott is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
4