Search code examples
multithreadingdelphitimingsynchronize

Timing and VCL synchronize (in/from thread)


I would like to refresh a Treenode.text (with the elapsed time) and use a timer from the same thread. As i read its not recommend to use TTimer* in a thread, but then, what to use instead? Thank You.

*I want to use some timing instead of sleep(). Not just because thats cheesy(?), but i have to, because otherwise i can refresh treenodetext only in every sec.) >>

unit master_slave

...

Tsrch_slave_thread = class(TThread)   
protected
  procedure Execute; override;
public
  master: TMaster;         
end;

TMaster = class(TObject)
private
  ...
  FMasterNode: TTreeview; 
  Fsw: TStopWatch;
  Fslave_search_thread : Tsrch_slave_thread;
  ...
end;

...

implementation

...

procedure Tsrch_slave_thread.Execute;
var
  searchactive: integer;
begin
  while not terminated do begin
    searchactive := master.CMD_LISTCNT 
    if searchactive = 1 then //(master.CMD_LISTCNT's return value = 1, if master finished search on the bus)
      exit;
    sleep(1000); //dont want to flood the master with UDP packets... (master.CMD_LISTCNT sends UDP packets)
    synchronize(procedure begin
      with FmasterNode do  
        text := text + floattostr(Fsw.ElapsedMilliseconds / 1000);
    end);
  end;
end;

Solution

  • Instead of Sleep(1000), use a waitable event.

    For example TSimpleEvent.

    FMySimpleEvent.WaitFor(1000);
    

    If you want to exit the thread early, override the TThread.DoTerminate method and call:

    FMySimpleEvent.SetEvent;
    

    Something like this:

    procedure Tsrch_slave_thread.Execute;
    var
      searchactive: integer;
    begin
      while not terminated do begin
        searchactive := master.CMD_LISTCNT 
        if searchactive = 1 then (master.CMD_LISTCNT's return value = 1, if search finished)
          exit;
        if (FMySimpleEvent.WaitFor(1000) = wrTimeOut) then
          synchronize(procedure begin
            with FmasterNode do  
              text := text + floattostr(Fsw.ElapsedMilliseconds / 1000);
          end);
      end;
    end;
    
    procedure Tsrch_slave_thread.DoTerminate;
    begin
      Inherited;
      FMySimpleEvent.SetEvent;
    end;