2011-07-06 3 views
1

먼저주의해서 읽으십시오.WaitForSingleObject 문제

CTest 클래스의 CreateInstance에서 생성 된 작업자 스레드가 있습니다. 다음은 클래스의 프로토 타입입니다. hThread는 스레드에 대한 핸들이고 hEventShutdown은 프로그램이 종료 될 때 스레드를 종료하는 데 사용되는 이벤트입니다. WaitForShutdown은 hEventShutdown 신호를 보내고 스레드가 정상적으로 종료 될 때까지 스레드 핸들을 대기하는 데 사용되는 공용 함수입니다. WaitForShutdown은 응용 프로그램의 종료에서 호출됩니다. 주의 깊게 코드를 보면

//pseudocode 
CTest 
{ 
public: 
CTest* CreateInstance(); 
static threadproc(void *pv); 
void WaitForShutdown(); 

public: 
HANDLE hThread; 
HANDLE hEventShutdown; 

} 

void CTest::CTest* CreateInstance() 
{ 
    // spawn a thread, pass 'this' pointer to thread , use beginthreadex 

    hThread = beginthreadex (threadproc, this); 
} 


unsigned int CTest::threadproc(void *pv) 
{ 

    Ctest *ptest = (Ctest*)pv; 

    do 
    { 
     HANDLES hArray[2] = { pv->hEventShutdown, someotherhandle } 

     dwResult = Waitformultipleobjects(hArrary , 2); 

    if (dwResult == WAIT_OBJECT_0) 
     delete pTest; // since it is allocated dynamically (This is required due to some known reasons in my code) 

    if(dwResult == WAIT_OBJECT_0 + 1) 
     Doprocessing(); //DoProcessing when other thread signal someotherhandle 

    }while (1) 

void CTest::WaitForShutdown() 
{ 
    SetEvent (hEventShutdown); 

    WaitForSingleObject (hThread,INFINITE); 

} 

void CTest::~CTest() 
{ 
    Closehandle(hThread) 
    Closehandle(hEventShutdown); 
} 

지금, 당신이 그 이벤트가 WaitForShutdown 함수에서 신호를 찾을 것입니다, 스레드는 WaitForMultipleOjbects 나오고 CTest의 포인터를 삭제합니다. 그것은 분명히 스레드 핸들 (hThread)을 닫을 것입니다 CTest의 소멸자가 호출됩니다. WaitForShutdown WaitForSingleObject 실제로 스레드 핸들을 기다리고 있습니다. 그래서 여기의 행동은 정의되지 않을 것입니다. (틀렸다고 생각하면 제게 고칠 수 있습니다). 또 다른 문제는 Ctit의 소멸자가 WaitForSingleObject가 멤버 hThread에서 올바르지 않은 경우 대기 할 때 호출됩니다. 몇 가지 이유 때문에 거기에 있어야하기 때문에 스레드에서 삭제 pTest를 제거 할 수 없습니다.

위의 해결 방법을 어떻게 제안 하시겠습니까? 내가 생각할 수있는 솔루션의

커플 :

  1. 나는 다른지도에서 스레드 핸들을 유지할 수 있지만 그것을 할 싶지 않다.
  2. WaitForShutdown의 WaitForSingleObject 전에 스레드 핸들을 일부 로컬 변수에 복사하여 기다릴 수 있습니다. 돈? 모르지? 너는 나에게 말한다.
  3. 또는 Duplicatehandle API를 사용하여 WaitForSingleObject 전에 기존 스레드 핸들 참조를 가져 와서 기다립니다. 그것이 정확하다는 것을 모릅니다. 원래의 CloseHandle 이후에 복제 핸들이 살아 있는지 알려지지 않습니다.
  4. 스레드 ID를 유지하고 스레드 ID에서 스레드 핸들을 가져오고 WaitForShutdown의 스레드 핸들을 계속 대기합니다. 이것은 좀 더 우아 해 보이지만 스레드 ID에서 핸들을 얻는 방법이 있는지 모르겠습니다.

수정하십시오.

귀하의 의견 감사합니다.

답변

2

가장 간단한 방법은 WaitForSingleObject이 반환 한 후 WaitForShutdown에서 스레드를 삭제하는 것입니다. 이렇게하면 필요한 모든 핸들 (더 중요한 것은 오브젝트 자체)이 끝까지 살아남을 수 있습니다.

1

나는이 조각을 그대로 사용했다. 작동하는 것 같고 충돌하지 않습니다. WaitforSingleObject(hThread,INFINITE)에서 나가기 전에 이상하게도 CloseHandle(hthread)으로 전화 할 수 있습니다. 물론 "학술"스레드에 가입하는 방법은 WaitForSingleObject(hThread,INFINITE)보다 먼저 CloseHandle(hThread)이됩니다. 그래서 그것은 제 제안입니다 - 이런 식으로하십시오.

더 이상 추가하지 않아도됩니다.

+0

"학술적"이상의 것이 정확합니다. 핸들을 닫은 후에는 더 이상 유효하지 않습니다. –