在线请教,创建200个线程后,如何等待和判断线程是否完成?
听说WaitForMultipleObjects最多只能等待64个线程,不知该如何解决?

解决方案 »

  1.   

    Windows核心编程一书中讲得有一个中
    WaitForMultiExpression
      

  2.   

    // Function to wait on mutiple Boolean expressions
    DWORD WINAPI WaitForMultipleExpressions(DWORD nExpObjects, 
       CONST HANDLE* phExpObjects, DWORD dwMilliseconds) {   // Allocate a temporary array because we modify the passed array and
       // we need to add a handle at the end for the hsemOnlyOne semaphore.
       PHANDLE phExpObjectsTemp = (PHANDLE)
          _alloca(sizeof(HANDLE) * (nExpObjects + 1));
       CopyMemory(phExpObjectsTemp, phExpObjects, sizeof(HANDLE) * nExpObjects);
       phExpObjectsTemp[nExpObjects] = NULL;  // Put sentinel at end   // Semaphore to guarantee that only one expression gets satisfied
       HANDLE hsemOnlyOne = CreateSemaphore(NULL, 1, 1, NULL);
       
       // Expression information: 1 per possible thread
       EXPRESSION Expression[MAXIMUM_WAIT_OBJECTS];   DWORD dwExpNum  = 0;    // Current expression number
       DWORD dwNumExps = 0;    // Total number of expressions   DWORD dwObjBegin = 0;   // First index of a set
       DWORD dwObjCur   = 0;   // Current index of object in a set   DWORD dwThreadId, dwWaitRet = 0;   // Array of thread handles for threads: 1 per expression
       HANDLE ahThreads[MAXIMUM_WAIT_OBJECTS];   // Parse the callers handle list by initializing a structure for
       // each expression and adding hsemOnlyOne to each expression.
       while ((dwWaitRet != WAIT_FAILED) && (dwObjCur <= nExpObjects)) {      // While no errors, and object handles are in the caller's list...      // Find next expression (OR-expressions are separated by NULL handles)
          while (phExpObjectsTemp[dwObjCur] != NULL) 
             dwObjCur++;
          
          // Initialize Expression structure which an OR-thread waits on
          phExpObjectsTemp[dwObjCur] = hsemOnlyOne;
          Expression[dwNumExps].m_phExpObjects =  &phExpObjectsTemp[dwObjBegin];
          Expression[dwNumExps].m_nExpObjects  =  dwObjCur - dwObjBegin + 1;      if (Expression[dwNumExps].m_nExpObjects > MAXIMUM_WAIT_OBJECTS) {
             // Error: Too many handles in single expression
             dwWaitRet = WAIT_FAILED;
             SetLastError(ERROR_SECRET_TOO_LONG);
          }      // Advance to the next expression
          dwObjBegin = ++dwObjCur;
          if (++dwNumExps == MAXIMUM_WAIT_OBJECTS) {
             // Error: Too many expressions
             dwWaitRet = WAIT_FAILED;
             SetLastError(ERROR_TOO_MANY_SECRETS);
          }
       }   if (dwWaitRet != WAIT_FAILED) {      // No errors occurred while parsing the handle list      // Spawn thread to wait on each expression
          for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {         ahThreads[dwExpNum] = chBEGINTHREADEX(NULL, 
                1, // We only require a small stack
                WFME_ThreadExpression, &Expression[dwExpNum], 
                0, &dwThreadId);
          }      // Wait for an expression to come TRUE or for a timeout
          dwWaitRet = WaitForMultipleObjects(dwExpNum, ahThreads, 
             FALSE, dwMilliseconds);      if (WAIT_TIMEOUT == dwWaitRet) {         // We timed-out, check if any expressions were satisfied by 
             // checking the state of the hsemOnlyOne semaphore.
             dwWaitRet = WaitForSingleObject(hsemOnlyOne, 0);         if (WAIT_TIMEOUT == dwWaitRet) {            // If the semaphore was not signaled, some thread expressions
                // was satisfied; we need to determine which expression.
                dwWaitRet = WaitForMultipleObjects(dwExpNum, 
                   ahThreads, FALSE, INFINITE);         } else {            // No expression was satisfied and WaitForSingleObject just gave
                // us the semaphore so we know that no expression can ever be 
                // satisfied now -- waiting for an expression has timed-out.
                dwWaitRet = WAIT_TIMEOUT;
             }
          }      // Break all the waiting expression threads out of their 
          // wait state so that they can terminate cleanly.
          for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {         if ((WAIT_TIMEOUT == dwWaitRet) || 
                 (dwExpNum != (dwWaitRet - WAIT_OBJECT_0))) {            QueueUserAPC(WFME_ExpressionAPC, ahThreads[dwExpNum], 0);
             }
          }#ifdef _DEBUG
          // In debug builds, wait for all of expression threads to terminate 
          // to make sure that we are forcing the threads to wake up. 
          // In non-debug builds, we'll assume that this works and 
          // not keep this thread waiting any longer.
          WaitForMultipleObjects(dwExpNum, ahThreads, TRUE, INFINITE);
    #endif      // Close our handles to all the expression threads
          for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {
             CloseHandle(ahThreads[dwExpNum]);
          }
       }  // error occurred while parsing   CloseHandle(hsemOnlyOne);
       return(dwWaitRet);
    }
      

  3.   

    老兄你搞那么多线程?你的CPU是奔100吗?设计得改。
      

  4.   

    做个计数器有问题吗。。定义同步变量,每次只允许一个线程将计数器+1,主线程等待计数器为0时再退出。Windows核心对象的引用不就是使用这个方式实现的吗?
      

  5.   

    做个记数器   注意是Critical Section
      

  6.   

    我做了计数器啦,我用
    while (Count > 0)
    {
    Sleep(50);
    }
    在等待,当扫描数小于5000时基本没问题,(就是有时时间太长)
    当大于5000时,就出问题,一直等不到?而且不太稳定,一时好,一时就出错了?
       不知该怎么解决?
      

  7.   

    我做了计数器啦,我用
    while (Count > 0)
    {
    Sleep(50);
    }
    在等待,当扫描数小于5000时基本没问题,(就是有时时间太长)
    当大于5000时,就出问题,一直等不到?而且不太稳定,一时好,一时就出错了?
       不知该怎么解决?
      

  8.   

    200个线程已经很多了,呵呵,看能否再精简一些,线程越多越不好维护!
    另外 Sleep(50);太长了,Sleep(10)足够了。
      

  9.   

    TestThread ss[200];
    for(int i=0;i<200;i++)
    {
    ss[i].i=i;
    ss[i].start();
    }for(i=0;i<200;i++)
      ss[i].waitCurThread();
      

  10.   

    class TestThread:
    public Thread
    {
    public:
    int i;
    virtual void run()
    {
    printf("%d\r\n",i);
    }
    };
      

  11.   

    #pragma once
    #pragma warning(disable:4800)
    #include <process.h>class Thread
    {
    private:
    HANDLE  hThread; //当前线程句柄
    unsigned ThreadId; //当前线程ID
    public:
    static unsigned __stdcall startThread(void *threadObject)
    {
    if(threadObject==NULL)
    return E_INVALIDARG;
    Thread *curThread=(Thread *)threadObject;
    curThread->Pre();
    curThread->run();
    curThread->End();
    return S_OK;
    } Thread(void):hThread(NULL),ThreadId(0){} virtual ~Thread(void)
    {
    if(!isAlive())
    {
    CloseHandle(hThread);
    ThreadId=0;
    }
    else
    {
    TerminateThread(hThread,0);
    CloseHandle(hThread);
    ThreadId=0;
    }
    }
    virtual void stop() {return;}
    //线程开始准备
    virtual void Pre() {return;}
    //线程处理逻辑
    virtual void run()=0;
    //线程终止处理
    virtual void End() {return;}
    //判断线程是否启动
    inline bool Thread::isAlive()
    {
    if(hThread==NULL) return false;
    DWORD exitCode;
    if(GetExitCodeThread(hThread,&exitCode))
    {
    if(exitCode==STILL_ACTIVE)
    return true;
    }
    return false;
    }
    //启动并开始线程
    bool start()
    {
    DWORD exitCode;
    if(GetExitCodeThread(hThread,&exitCode))
    {
    if(exitCode==STILL_ACTIVE)
    return false;
    }
    CloseHandle(hThread);
    hThread=(HANDLE)_beginthreadex(NULL,0,Thread::startThread,(void *)this,0,&ThreadId);
    return hThread!=0;
    } //中断该线程
    inline bool terminate()
    {
    if(!isAlive())
    return true;
    else
    return (bool)TerminateThread(hThread,0);
    }
    //启动并挂起程序
    bool startsuspend()
    {
    //如果该线程以经启动,直接返回
    if(isAlive())
    return false;
    CloseHandle(hThread);
    hThread=(HANDLE)_beginthreadex(NULL,0,Thread::startThread,(void *)this,CREATE_SUSPENDED,&ThreadId);
    return hThread!=0;
    } //换醒线程
    inline bool resume(){return ResumeThread(hThread)!=-1;}
    //等待当前线程完
    inline void waitCurThread(){WaitForSingleObject(hThread,INFINITE);}
    inline void waitCurThread(DWORD dwMilliseconds){WaitForSingleObject(hThread,dwMilliseconds);}
    inline unsigned getThreadId() {ASSERT(ThreadId!=NULL);return ThreadId;}
    inline HANDLE getThreadHandle() {ASSERT(hThread!=NULL);return hThread;}
    };
      

  12.   

    已解决,送分。Totogecy() ( ) 信誉:100  2005-04-06 16:51:00  得分: 0  
       做个记数器   注意是Critical Section