Friday, 2 December 2016

Wait for thread without freezing the application - Indy [example]

Use the TThread.OnTerminate event to know when the thread has finished:
type
  TSendThread = class(TThread)
  private
    http : TIdHTTP;
    Line: string;
    procedure AddLine;
  protected
    procedure Execute; override;
  public
    constructor Create; reintroduce;
    destructor Destroy; override;
    URL : String;
    Method : String;
    property ReturnValue;
  end;

constructor TSendThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
  http := TIdHTTP.Create;
end;

destructor TSendThread.Destroy;
begin
  http.Free;
  inherited;
end;

procedure TSendThread.Execute;
begin
  Line := http.Get(URL);
  Synchronize(AddLine);
  ReturnValue := 1;
end;

procedure TSendThread.AddLine;
begin
  Form1.Memo1.Lines.Add(Line);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  t : TSendThread;
begin
  t := TSendThread.Create;
  t.URL := 'http://www.url.com/';
  t.OnTerminate := ThreadTerminated;
  t.Start;
end;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin
  ShowMessage(IntToStr(TSendThread(Sender).ReturnValue));
end;
If you want to use a loop to wait for the thread to finish, without blocking the UI, then you can do it like this:
constructor TSendThread.Create;
begin
  inherited Create(True);
  //FreeOnTerminate := True; // <-- remove this
  http := TIdHTTP.Create;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  t : TSendThread;
  h : THandle;
begin
  t := TSendThread.Create;
  try
    t.URL := 'http://www.url.com/';
    t.Start;
    h := t.Handle;
    repeat
      case MsgWaitForMultipleObjects(1, h, 0, INFINITE, QS_ALLINPUT) of
        WAIT_OBJECT_0:   Break;
        WAIT_OBJECT_0+1: Application.ProcessMessages;
        WAIT_FAILED:     RaiseLastOSError;
      else
        Break;
      end;
    until False;
    ShowMessage(IntToStr(t.ReturnValue));
  finally
    t.Free;
  end;
end;

credit: Remy Lebeau - http://stackoverflow.com/

0 comments:

Post a Comment