gpt4 book ai didi

multithreading - 为什么 WaitForMultipleObjects 在使用多个线程句柄时会失败?

转载 作者:行者123 更新时间:2023-12-03 14:39:40 26 4
gpt4 key购买 nike

在下面的测试程序中,每个测试线程在开始执行时将其句柄添加到全局 TThreadList 中,并在执行即将结束时从同一列表中删除其句柄。

出于测试目的,此外,每个线程确保在主线程锁定列表之前添加其句柄(以复制其句柄并开始等待它们完成)。这些线程还确保在主线程锁定列表之前它们不会删除其句柄。

测试程序在最多 50-60 个线程下运行良好。之后,WaitForMultipleObjects 调用开始失败,并显示 WAIT_FAILEDGetLastError 返回 87 (ERROR_INVALID_PARAMETER)。目前它启动了 100 个线程。我的问题是,我做错了什么?

该程序是使用 XE2 - update 4、32 位目标平台编译的。测试盒为W7x64。

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
windows,
sysutils,
classes,
syncobjs;

type
TTestThread = class(TThread)
private
FAckStarted: TEvent;
function GetAckHandle: THandle;
class var
ThreadList: TThreadList;
WaitEnd: THandle;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
property AckHandle: THandle read GetAckHandle;
end;

{.$DEFINE FREEONTERMINATE}

constructor TTestThread.Create;
begin
inherited Create(True);
FAckStarted := TEvent.Create;
{$IFDEF FREEONTERMINATE}
FreeOnTerminate := True;
{$ENDIF}
end;

destructor TTestThread.Destroy;
begin
FAckStarted.Free;
inherited;
end;

procedure TTestThread.Execute;
begin
// OutputDebugString(PChar(Format('%d starting -------------', [Handle])));
ThreadList.Add(Pointer(Handle));
FAckStarted.SetEvent;

NameThreadForDebugging(AnsiString(IntToStr(Handle)));

WaitForSingleObject(WaitEnd, INFINITE);
ThreadList.Remove(Pointer(Handle));
// OutputDebugString(PChar(Format('%d leaving -------------', [Handle])));
end;

function TTestThread.GetAckHandle: THandle;
begin
Result := FAckStarted.Handle;
end;

const
NumThreads = 100;

var
DeferThreadEnd: TEvent;
ThreadList: array of TThread;
i: Integer;
Thread: TTestThread;
WaitThreadStart: THandle;
LockList: TList;
LockListCount: Integer;
ThreadHandleArr: array of THandle;
WaitRet: DWORD;
begin
IsMultiThread := True;
ReportMemoryLeaksOnShutdown := True;

TTestThread.ThreadList := TThreadList.Create;
DeferThreadEnd := TEvent.Create;
TTestThread.WaitEnd := DeferThreadEnd.Handle;

SetLength(ThreadList, NumThreads);
for i := 0 to NumThreads - 1 do begin
Thread := TTestThread.Create;
ThreadList[i] := Thread;
WaitThreadStart := Thread.GetAckHandle;
Thread.Start;
WaitForSingleObject(WaitThreadStart, INFINITE);
end;

LockList := TTestThread.ThreadList.LockList;
LockListCount := LockList.Count;
SetLength(ThreadHandleArr, LockListCount);
for i := 0 to LockListCount - 1 do
{$IFDEF FREEONTERMINATE}
Win32Check(DuplicateHandle(GetCurrentProcess, THandle(LockList[i]),
GetCurrentProcess, @ThreadHandleArr[i], SYNCHRONIZE, True, 0));
{$ELSE}
ThreadHandleArr[i] := THandle(LockList[i]);
{$ENDIF}
TTestThread.ThreadList.UnlockList;

DeferThreadEnd.SetEvent;
if LockListCount > 0 then begin
Writeln('waiting for ', LockListCount, ' threads');
WaitRet := WaitForMultipleObjects(LockListCount,
PWOHandleArray(ThreadHandleArr), True, INFINITE);
case WaitRet of
WAIT_OBJECT_0: Writeln('wait success');
WAIT_FAILED: Writeln('wait fail:', SysErrorMessage(GetLastError));
end;
end;

for i := 0 to Length(ThreadList) - 1 do begin
{$IFDEF FREEONTERMINATE}
Win32Check(CloseHandle(ThreadHandleArr[i]));
{$ELSE}
ThreadList[i].Free;
{$ENDIF}
end;
DeferThreadEnd.Free;
TTestThread.ThreadList.Free;
Writeln('program end');
Readln;
end.

最佳答案

WaitForMultipleObjects() documentation状态:

The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.

MAXIMUM_WAIT_OBJECTS的值是 64(在 winnt.h 中定义),因此 100 个句柄超出了限制。但是,该文档还解释了如何克服该限制:

To wait on more than MAXIMUM_WAIT_OBJECTS handles, use one of the following methods:

  • Create a thread to wait on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other handles. Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS.

  • Call RegisterWaitForSingleObject to wait on each handle. A wait thread from the thread pool waits on MAXIMUM_WAIT_OBJECTS registered objects and assigns a worker thread after the object is signaled or the time-out interval expires.

查看this question的答案有关第一种技术的示例。

关于multithreading - 为什么 WaitForMultipleObjects 在使用多个线程句柄时会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39380131/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com