Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for thread without freezing the application

I'm trying to put an indy TIdHttp in a thread, I have tried this :

type
  TSendThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  public
    http : TIdHTTP;
    URL : String;
    Method : String;
    property ReturnValue;
  end;

procedure TSendThread.Execute;
begin
  form1.Memo1.lines.Add(http.Get(URL));
  ReturnValue := 1;
end;

And in the main :

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

My problem here is that the next instruction gets executed(showmessage) without waiting the thread to be done, i tried to use the "WaitFor" but it freezes the application.

Is there any other workaround?

Thank you.

like image 287
Ouerghi Yassine Avatar asked Jun 04 '13 01:06

Ouerghi Yassine


People also ask

How do you make a thread wait for some time?

In between, we have also put the main thread to sleep by using TimeUnit. sleep() method. So the main thread can wait for some time and in the meantime, T1 will resume and complete its execution.

Does wait method release the lock?

The wait function doesn't release "all locks", but it does release the lock associated with the object on which wait is invoked.

What will happen if multiple threads accessing the same resource?

Multiple threads accessing shared data simultaneously may lead to a timing dependent error known as data race condition. Data races may be hidden in the code without interfering or harming the program execution until the moment when threads are scheduled in a scenario (the condition) that break the program execution.

How do you cancel a waiting thread?

Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected. A thread will also move to the dead state automatically when it reaches the end of its method.


1 Answers

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;
like image 200
Remy Lebeau Avatar answered Oct 02 '22 14:10

Remy Lebeau