Stefan
Stefan

Reputation: 21

Access VCL from other thread

I wrote a communication class based on TThread, which would send some data and receive a reply. I want the method to:

  1. sent the data (this is a non blocking procedure)
  2. wait for a reply or timeout
  3. show the data received in a vcl control
  4. give back control to the caller

Here is how I try to do,

procedure TForm1.Button1Click(Sender: TObject);
begin
  for i := 1 to 5 do // send 5 commands
    mycomm.SendCommand();
end;

procedure TMyComm.ShowData();
begin
  Form1.Memo1.Lines.Add('Frame received');
end;

procedure TMyComm.SendCommand();
begin
    //build frame and put it on interface here
    //...

    event.WaitFor(3000);

    //show received frame if no timeout in VCL
    //...
end;

procedure TMyComm.Execute();
begin
    while not Terminated do
    begin
      if receive() then //blocks until frame is received
      begin
        Synchronize(ShowData); //hangs :-(
        event.SetEvent;
      end;
    end,
end;

Of course this will result in a deadlock, but how can I achieve that my VCL is updated immediately after each received frame?

Upvotes: 1

Views: 279

Answers (1)

Peter-John Jansen
Peter-John Jansen

Reputation: 643

You can use a anonymous thread, this will only execute the rest of the code after the thread has finished, change it to suite your needs. You can find the AnonThread Unit in :

C:\Users\Public\Documents\RAD Studio\12.0\Samples\Delphi\RTL\CrossPlatform Utils

uses
 AnonThread 

var
    GetFrame :TAnonymousThread<Boolean>;

begin
    GetFrame := TAnonymousThread<Boolean>.Create(function : Boolean
    begin
    // Start your execution      
    end,
    procedure (AResult : Boolean)
    begin
    // Wil only execute after the thread has run its course, also safe to do UI updates       
    end,
    procedure (AException : Exception)
    begin
        ShowMessage('Error : ' + AException.Message);
    end);

Upvotes: 0

Related Questions