我有一个应用程序有50个线程做某事我希望我的程序(btnTestClick)等待所有线程终止。我已经尝试使用全局变量作为计数器和WaitForMultipleObjects(threadCount, @threadArr, True, INFINITE);
但是程序永远不会等待所有线程终止。这就是我的线程的样子:
TClientThread = class(TThread)
protected
procedure Execute; override;
public
constructor create(isSuspended : Boolean = False);
end;
以下是构造函数和执行过程:
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;
我的OnButtonClick就是这样:
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;
答案 0 :(得分:16)
您的代码为:
WaitForMultipleObjects(clientThreadsNum, @clientThreads, True, INFINITE);
其中clientThreads
的类型为:
array of TClientThread
现在,@clientThreads
是动态数组的地址。这是指向第一个线程对象的指针的地址。但是你应该将指针传递给第一个线程句柄,这完全不同。所以你需要形成一个线程句柄列表:
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);
如果检查了返回值,您会发现对WaitForMultipleObjects
的调用不正确。 Win32编程的一个基本规则是你应该努力不破坏的规则,就是检查函数调用返回的值。
我相信您对WaitForMultipleObjects
的来电将返回WAIT_FAILED
。当发生这种情况时,您可以致电GetLastError
以找出问题所在。您应该修改代码以执行正确的错误检查。请仔细阅读文档,了解如何操作。