我生成一个管理线程,然后创建多个子线程使其执行,并在管理线程中用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;

解决方案 »

  1.   


    另外,我看见很多人的用法都是把生成的线程句柄值传递到一个句柄数组中,
    比如 数组名[i]:=线程名.Handle
    ,然后调用WaitForMultipleObjects等待执行结束,但这样就有一个问题:数组中的值岂不是永远不会改变?
    如果真是这样,WaitForMultipleObjects函数又是怎样判断返回的?
      

  2.   

    WaitForMultipleObjects将用于等待多个对象变为有信号状态,函数原型如下: DWORD 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:表示超过规定时间。 
      

  3.   

    进程/线程间同步http://www.vchelp.net/wyy/tour/teach_sp_44.htm
      

  4.   

    这些我都明白.
    请各位看看代码中的问题,我搞不懂为什么总是返回WAIT_FAILED
      

  5.   

    DWORD WaitForMultipleObjects(
      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, 也不是信号触发了
      

  6.   

    如果结束循环条件改成 until R=WAIT_OBJECT_0  也是一样,根本没返回这个值.还是死循环.
    我是想开几个线程依次去读一个全局数组的值并执行某个操作.
    哪位有类似的源码?
      

  7.   

    Pointer(@tmpThreadHandle[0]^)错了, 这句相当于pointer(tmpThreadHandle[0]), 也就是将tmpThreadHandle[0]的值强制转换成pointer. 而这个api明明要求的是tmpThreadHandle这个数组的首地址. 所以这里改成PWOHandleArray(tmpThreadHandle)就可以了(因为tmpThreadHandle本来就是个指针, 指向动态数组的第一个元素, 所以只要将其强制类型转换成waitformultipleobjects要求的类型就可以了).
      

  8.   

    噢,这是我写错了.
    原本定义的线程句柄数组类型为PLONGWORD.
    我想请各位看看这样写逻辑上有没有错误.
      

  9.   

    没看到关键的FMax变量的定义和赋值, 你的tmpThreadHandle总共只有8个元素, 如果FMAX=0或FMAX>8那么waitformultipleobjects肯定返回失败的.
      

  10.   

    去MSDN 好好看看这个函数的说明....
    包括返回值,参数还有 Windows核心编程有较详细的说明.