Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for multiple threads to terminate in delphi?

I have an application with 50 threads that do something and I want my procedure (btnTestClick) to wait until all threads are terminated. I've tried with global variable as counter and with WaitForMultipleObjects(threadCount, @threadArr, True, INFINITE); but the procedure never waits for all threads to terminate.Here is how my thread looks like :

TClientThread = class(TThread)
  protected
    procedure Execute; override;
public
  constructor create(isSuspended : Boolean = False);
end;

And here are the constructor and the execute procedure :

constructor TClientThread.create(isSuspended : Boolean);
begin
  inherited Create(isSuspended);
  FreeOnTerminate := True;
end;

procedure TClientThread.Execute;
var
begin
  inherited;
  criticalSection.Enter;
  try
    Inc(globalThreadCounter);
  finally
    criticalSection.Leave;
  end;
end; 

And my OnButtonClick is this :

procedure TMainForm.btnTestClick(Sender: TObject);
var
  clientThreads : array of TClientThread;
  i, clientThreadsNum : Integer;
begin
  clientThreadsNum := 50;
  SetLength(clientThreads, clientThreadsNum);
  for i := 0 to Length(clientThreads) - 1 do begin // РЕДАКТИРАЙ !!
    clientThreads[i] := TClientThread.Create(True);
  end;
  // here I will assign some variables to the suspended threads, but that's not important here 
  for i := 0 to Length(clientThreads) - 1 do begin
    clientThreads[i].Start;
  end;

  WaitForMultipleObjects(clientThreadsNum, @clientThreads, True, INFINITE);
  // do something after all threads are terminated 
end;
like image 968
Viktor Anastasov Avatar asked May 29 '14 15:05

Viktor Anastasov


People also ask

Which command is used to wait for the termination of a thread?

Use pthread_join(3THR) to wait for a thread to terminate. Prototype: int pthread_join(thread_t tid , void ** status );

What is thread in Delphi?

Multi-threading in Delphi lets you create applications that include several simultaneous paths of execution. A normal Delphi application is single-threaded, which means all VCL objects access their properties and execute their methods within this single thread.

How to temporarily suspend execution in Delphi?

Mon, 24 Oct 2016 | Delphi Guide. If your thread must wait for another thread to finish some task, you can tell your thread to temporarily suspend execution. You can either wait for another thread to completely finish executing, or you can wait for another thread to signal that it has completed a task.

How does the main thread work in Delphi?

Actually every Delphi application has main thread which executes when the application starts and terminates when application exits. And during application run when we don't do anything then main thread suspends for some time and when user again do some action main thread resumes and starts executing the actions.

How do you wait for a thread to finish executing?

Waiting for a thread to finish executing To wait for another thread to finish executing, use the WaitFor method of that other thread. WaitFor doesn't return until the other thread terminates, either by finishing its own Execute method or by terminating due to an exception.

How do I temporarily suspend execution of a thread?

If your thread must wait for another thread to finish some task, you can tell your thread to temporarily suspend execution. You can either wait for another thread to completely finish executing, or you can wait for another thread to signal that it has completed a task. Waiting for a thread to finish executing


1 Answers

You code reads:

WaitForMultipleObjects(clientThreadsNum, @clientThreads, True, INFINITE);

where clientThreads is of type:

array of TClientThread

Now, @clientThreads is the address of the dynamic array. That is the address of a pointer to the first thread object. But you are expected to pass a pointer to the first thread handle, something utterly different. So instead you need to form a list of thread handles:

var
  ThreadHandles: array of THandle;
....
SetLength(ThreadHandles, Length(clientThreads));
for i := 0 to high(clientThreads) do
  ThreadHandles[i] := clientThreads[i].Handle;
WaitForMultipleObjects(clientThreadsNum, Pointer(ThreadHandles), True, INFINITE);

You would have discovered that your call to WaitForMultipleObjects was incorrect had you checked the return value. A basic rule of Win32 programming, one that you should strive not to break, is that you check the values returned by function calls.

I believe that your call to WaitForMultipleObjects will return WAIT_FAILED. When that happens you can call GetLastError to find out what went wrong. You should modify your code to perform proper error checking. Take good care to read the documentation to find out how to do so.

like image 89
David Heffernan Avatar answered Sep 27 '22 20:09

David Heffernan