WaitForMultipleObjects는 몇개의 Thread가 동작이 끝날 때까지 다음 루틴을 수행하지 않고 대기하는 역할을 수행한다.

 

MSDN을 보면

 

WaitForMultipleObjects

This function returns when one of the following occurs:

  • Either any one of the specified objects are in the signaled state.
  • The time-out interval elapses.
DWORD WaitForMultipleObjects( DWORD nCount,  CONST HANDLE *lpHandles,  BOOL fWaitAll,  DWORD dwMilliseconds );

Parameters

nCount
Specifies the number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.
lpHandles
Pointer to an array of object handles. For a list of the object types whose handles can be specified, see the following Remarks section. The array can contain handles of objects of different types.
fWaitAll
Specifies the wait type. This parameter must be set to FALSE. This causes function to return when the state of any one of the objects set to is signaled. The return value indicates the object whose state caused the function to return.
dwMilliseconds
Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the conditions specified by the bWaitAll parameter are not met. If dwMilliseconds is zero, the function tests the states of the specified objects and returns immediately. If dwMilliseconds is INFINITE, the function’s time-out interval never elapses.

위와 같은 것으로 정의 되어 있다.

이 함수의 특성은 모든 Thread들이 종료될 때까지 대기 하기 때문에 하나라도 종료가 되지 않으면 다음 루틴을 실행하지 않기 때문에 DeadLock이 걸릴 위험이 존재한다. 또한 동시에 Wait할 수 있는 Thread의 갯수가 64개로 제한되어 있다는 점도 있다. 그래서 64개 이상의 Thread를 wait하기 위해서는 이 함수를 여러번 써주어야한다.

 

내가 봉착한 문제는 64개 이상이 Thread를 생성시에 WaitForMultipleObjects함수를 호출해도 return 값이 WAIT_FAILED라는 에러가 나고 GetLastError()함수를 통해서 값을 체크하면 6 invalid handle값이 넘어온다는 것이다.

 

이유는 _beginthread를 통해서 생성된 Thread 들은 종료시점을 정확하게 알 수 없기 때문에 제어가 불가능하다. 그래서 64개 이상의 Thread들을 대기할 경우에는 문제가 발생할 수 있다.

아래의 주석 처리된 _beginthread를 쓰면 문제가 발생할 수 있다.

 

그래서 _beginthreadex나  CreateThread를 써야만 이런 문제를 해결할 수 있다. 여기서는 종료상태가 체크가 가능하다.

 

// requestcount : 생성될 Thread 갯수가 저장된 variable

// _ThreadRegistration : Thread 의 함수 이름 ( 실행될 Thread 의 주소값이다. )

// registrationStruct : Thread에 넘어갈 parameter 구조체

 

HANDLE *pThreadId;
pThreadId = new HANDLE[requestcount];
 
DWORD dwThreadID;

for( DWORD i = 0 ; i < requestcount; i ++ ) 
{
    registrationStruct[i].userid = i+1;
    registrationStruct[i].pDlgParam = (LPVOID)this;
    pThreadId[i]=(HANDLE)CreateThread( NULL, 0, _ThreadRegistration, &registrationStruct[i], 0, &dwThreadID);
    //pThreadId[i]=(HANDLE)_beginthread(_ThreadRegistration, 0, (void *)&registrationStruct[i]);
    if( pThreadId[i] == NULL )
       AfxMessageBox("fail to create thread");

}
   
if( requestcount < MAXIMUM_WAIT_OBJECTS )
{
    DWORD dwRet = -1;
    dwRet = ::WaitForMultipleObjects(requestcount, pThreadId, TRUE, INFINITE);
    checkMultiObjects(dwRet);    // return value check routine
}
else
{
     int repeatwait = requestcount / 64;
     int remainwait = requestcount % 64;

     int temp1, temp2; 
     for(temp1=0, temp2=0; temp1 < repeatwait; temp1++, temp2 += MAXIMUM_WAIT_OBJECTS)
     {
         DWORD dwRet = -1;
         dwRet = ::WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, &pThreadId[temp2], TRUE, INFINITE);
         checkMultiObjects(dwRet);   // return value check routine
     }
     DWORD dwRet = -1;
     dwRet =  ::WaitForMultipleObjects( remainwait, &pThreadId[temp2], TRUE, INFINITE);
     checkMultiObjects(dwRet);    // return value check routine

}

if( pThreadId != NULL)
    delete []pThreadId;

'Development > C/C++' 카테고리의 다른 글

_WIN32_WINNT, _WIN32_IE 버전 값 정리  (0) 2011.08.13
[VC++]Win32에서의 유니코드  (0) 2011.08.13
[펌] Observer pattern (C++)  (0) 2011.08.13
[펌] Effective C++  (0) 2011.08.13
[펌] C++ 기초 강좌  (0) 2011.08.13
안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,