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;
Use pthread_join(3THR) to wait for a thread to terminate. Prototype: int pthread_join(thread_t tid , void ** status );
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.
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With