我生成一个管理线程,然后创建多个子线程使其执行,并在管理线程中用WaitForMultipleObjects循环等待所有子线程结束,参数1为所有子线程的句柄数组,但WaitForMultipleObjects函数返回的全部是WAIT_FAILED值,一直退不出循环,这是怎么回事?代码如下var
RoomCount:integer;
RoomPos:integer;
RoomAry:TRoomAry;
procedure TCodeManageThread.Execute;//管理线程
var
i:integer;
tmpList:TList;
tmpMax:integer;
tmpThreadHandle:array of THandle;//线程句柄数组
tmpEvent:array of THandle;//线程开始事件
R:DWORD;
begin
inherited;
try
FreeOnTerminate:=False;
FThreadList:=TThreadList.Create;
SetLength(tmpThreadHandle,8);
SetLength(tmpEvent,8);
try
tmpList:=FThreadList.LockList;
try
Screen.Cursor := crAppStart;
for i :=0 to 7 do
begin
tmpEvent[i]:=CreateEvent(nil,True,True,Pchar(IntToStr(i)));
tmpList.Add(TCodeThread.Create(False,@tmpEvent[i]));
tmpThreadHandle[i]:=TCodeThread(tmpList[i]).Handle;
end;
finally
FThreadList.UnlockList;
end;
except
OutputDebugString('键码退出事件数组出错');
Exit;
end;
RoomCount:=0;
RoomPos:=0;
tmpMax:=High(RoomAry);
repeat
for i :=0 to 7 do
{if RoomPos>tmpMax then
break
else}
if WaitForSingleObject(tmpEvent[i],100)=WAIT_OBJECT_0 then
try
if RoomPos>tmpMax then
begin
TCodeThread(tmpList[i]).FQuited:=True;
continue;
end;
EnterCriticalSection(FCritic);
TCodeThread(tmpList[i]).FPos:=RoomPos;
InterLockedIncrement(RoomPos);
TCodeThread(tmpList[i]).FIp:=RoomAry[TCodeThread(tmpList[i]).FPos].ip;
TCodeThread(tmpList[i]).FCodeList:=RoomAry[TCodeThread(tmpList[i]).FPos].CodeList;
ResetEvent(tmpEvent[i]);//给子线程发信号
LeaveCriticalSection(fCritic);
finally
Application.ProcessMessages;
end;
R:=WaitForMultipleObjects(FMax,Pointer(@tmpThreadHandle[0]^),True,0);
case R of
WAIT_OBJECT_0:OutputDebugString('object');
WAIT_FAILED:OutputDebugString('failed');
WAIT_TIMEOUT:OutputDebugString('timeout');
end;
until R<>WAIT_TIMEOUT;//这里返回值全是WAIT_FAILED
finally
for i :=0 to FMax-1 do
TCodeThread(tmpList[i]).Free;
tmpThreadHandle:=nil;
tmpEvent:=nil;
Screen.Cursor:=crDefault;
OutputDebugString('所有线程已退出');procedure TCodeThread.Execute;//子线程
begin
inherited;
try
FreeOnTerminate:=False;
repeat
if WaitForSingleObject(FEvent^,0)<>WAIT_OBJECT_0 then//FEVENT为管理线程的事件句柄指针
begin
SendCodes;
InterLockedIncrement(RoomCount);;
OutputDebugString(Pchar(s));
if RoomCount>High(RoomAry) then
FQuited:=True;
SetEvent(FEvent^);
end;
until FQuited=True;
finally
end;
end;
RoomCount:integer;
RoomPos:integer;
RoomAry:TRoomAry;
procedure TCodeManageThread.Execute;//管理线程
var
i:integer;
tmpList:TList;
tmpMax:integer;
tmpThreadHandle:array of THandle;//线程句柄数组
tmpEvent:array of THandle;//线程开始事件
R:DWORD;
begin
inherited;
try
FreeOnTerminate:=False;
FThreadList:=TThreadList.Create;
SetLength(tmpThreadHandle,8);
SetLength(tmpEvent,8);
try
tmpList:=FThreadList.LockList;
try
Screen.Cursor := crAppStart;
for i :=0 to 7 do
begin
tmpEvent[i]:=CreateEvent(nil,True,True,Pchar(IntToStr(i)));
tmpList.Add(TCodeThread.Create(False,@tmpEvent[i]));
tmpThreadHandle[i]:=TCodeThread(tmpList[i]).Handle;
end;
finally
FThreadList.UnlockList;
end;
except
OutputDebugString('键码退出事件数组出错');
Exit;
end;
RoomCount:=0;
RoomPos:=0;
tmpMax:=High(RoomAry);
repeat
for i :=0 to 7 do
{if RoomPos>tmpMax then
break
else}
if WaitForSingleObject(tmpEvent[i],100)=WAIT_OBJECT_0 then
try
if RoomPos>tmpMax then
begin
TCodeThread(tmpList[i]).FQuited:=True;
continue;
end;
EnterCriticalSection(FCritic);
TCodeThread(tmpList[i]).FPos:=RoomPos;
InterLockedIncrement(RoomPos);
TCodeThread(tmpList[i]).FIp:=RoomAry[TCodeThread(tmpList[i]).FPos].ip;
TCodeThread(tmpList[i]).FCodeList:=RoomAry[TCodeThread(tmpList[i]).FPos].CodeList;
ResetEvent(tmpEvent[i]);//给子线程发信号
LeaveCriticalSection(fCritic);
finally
Application.ProcessMessages;
end;
R:=WaitForMultipleObjects(FMax,Pointer(@tmpThreadHandle[0]^),True,0);
case R of
WAIT_OBJECT_0:OutputDebugString('object');
WAIT_FAILED:OutputDebugString('failed');
WAIT_TIMEOUT:OutputDebugString('timeout');
end;
until R<>WAIT_TIMEOUT;//这里返回值全是WAIT_FAILED
finally
for i :=0 to FMax-1 do
TCodeThread(tmpList[i]).Free;
tmpThreadHandle:=nil;
tmpEvent:=nil;
Screen.Cursor:=crDefault;
OutputDebugString('所有线程已退出');procedure TCodeThread.Execute;//子线程
begin
inherited;
try
FreeOnTerminate:=False;
repeat
if WaitForSingleObject(FEvent^,0)<>WAIT_OBJECT_0 then//FEVENT为管理线程的事件句柄指针
begin
SendCodes;
InterLockedIncrement(RoomCount);;
OutputDebugString(Pchar(s));
if RoomCount>High(RoomAry) then
FQuited:=True;
SetEvent(FEvent^);
end;
until FQuited=True;
finally
end;
end;
另外,我看见很多人的用法都是把生成的线程句柄值传递到一个句柄数组中,
比如 数组名[i]:=线程名.Handle
,然后调用WaitForMultipleObjects等待执行结束,但这样就有一个问题:数组中的值岂不是永远不会改变?
如果真是这样,WaitForMultipleObjects函数又是怎样判断返回的?
DWORD nCount, // 等待的对象数量
CONST HANDLE *lpHandles, // 对象句柄数组指针
BOOL fWaitAll, // 等待方式,
//为TRUE表示等待全部对象都变为有信号状态才返回,为FALSE表示任何一个对象变为有信号状态则返回
DWORD dwMilliseconds // 超时设置,以ms为单位,如果为INFINITE表示无限期的等待
);返回值意义:
WAIT_OBJECT_0 到 (WAIT_OBJECT_0 + nCount – 1):当fWaitAll为TRUE时表示所有对象变为有信号状态,当fWaitAll为FALSE时使用返回值减去WAIT_OBJECT_0得到变为有信号状态的对象在数组中的下标。
WAIT_ABANDONED_0 到 (WAIT_ABANDONED_0 + nCount – 1):当fWaitAll为TRUE时表示所有对象变为有信号状态,当fWaitAll为FALSE时表示对象中有一个对象为互斥量,该互斥量因为被关闭而成为有信号状态,使用返回值减去WAIT_OBJECT_0得到变为有信号状态的对象在数组中的下标。
WAIT_TIMEOUT:表示超过规定时间。
请各位看看代码中的问题,我搞不懂为什么总是返回WAIT_FAILED
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);
If dwMilliseconds is zero, the function tests the states of the specified objects and returns immediately R:=WaitForMultipleObjects(FMax,Pointer(@tmpThreadHandle[0]^),True,0);你最后一个参数为0, 也就是说是立即返回,那当然不是timeout, 也不是信号触发了
我是想开几个线程依次去读一个全局数组的值并执行某个操作.
哪位有类似的源码?
原本定义的线程句柄数组类型为PLONGWORD.
我想请各位看看这样写逻辑上有没有错误.
包括返回值,参数还有 Windows核心编程有较详细的说明.