2012-04-11 3 views
0

ActiveX 비디오 플레이어를 개발하고 있습니다. DLL의 in-process 구성 요소입니다. Visual Studio 2010을 사용하고 있습니다.win32 thread가 예기치 않게 activeX에서 종료됩니다 (C++)

구성 요소가로드 될 때 한 번 시작되고 Direct3D9 개체 및 Direct3D9 장치를 만든 다음 구성 요소 언로드에서 중지하고 이러한 개체를 파괴하는 별도의 스레드가 필요합니다. 구성 요소가 실행되는 동안이 스레드가 주기적으로 TestCooperativeLevel을 호출하고 필요한 경우 D3D 장치를 다시 설정하고 싶습니다.

클라이언트 응용 프로그램이 내 플레이어의 인스턴스를 여러 개 만들 수 있기 때문에이 작업을 수행하지만, D3D9 개체 및 장치 인스턴스를 하나만 사용하는 것이 좋습니다.

나는 정적 메서드와 멤버를 가진 클래스를 선언했으며, 생성자는 _beginthreadex()을 호출하고 스레드를 시작합니다.

다음은 코드 발췌 부분입니다 (오류 포함).

// .h 
class D3DManager { 
    static mutex d3; // mutex is my own class, just a wrapper around CriticalSection 
    static LPDIRECT3D9 g_d3d; 
    static LPDIRECT3DDEVICE9 g_d3ddev; 
    static D3DPRESENT_PARAMETERS g_d3dpp; 
    static int g_d3d_counter; 
    static HANDLE hthread; 
    static HANDLE exitev; 
    static bool exit_flag; 
    static mutex exit_mutex; 

public: 
    D3DManager(); 
    ~D3DManager(); 

    static unsigned int __stdcall thread(void *); 
    static void stop(void) { 
         exit_mutex.lock(); 
         exit_flag = true; 
         SetEvent(exitev); 
         exit_mutex.unlock(); } 

    static bool exit_signal(void) { 
         exit_mutex.lock(); 
         bool result = exit_flag; 
         exit_mutex.unlock(); 
         return exit_flag; } 

    static void CreateD3DDevice(LPDIRECT3D9& d3dobj, LPDIRECT3DDEVICE9& d3ddev); 
    static void DestroyD3DDevice(void); 
    static void GetSwapChain(HWND hwnd, LPDIRECT3DSWAPCHAIN9& chain); 
    static void release_d3d(void); 
    static void LockDevice(void) { d3.lock(); }; 
    static void UnlockDevice(void) { d3.unlock(); }; 
}; 



//.cpp 

        mutex D3DManager::d3; 
       LPDIRECT3D9 D3DManager::g_d3d = NULL; 
     LPDIRECT3DDEVICE9 D3DManager::g_d3ddev = NULL; 
    D3DPRESENT_PARAMETERS D3DManager::g_d3dpp; 
         int D3DManager::g_d3d_counter = 0; 
        HANDLE D3DManager::hthread; 
        HANDLE D3DManager::exitev; 
        bool D3DManager::exit_flag = false; 
        mutex D3DManager::exit_mutex; 

      // this variable will be single and shared by all activeX instances 
      static D3DManager d3dm; 


    D3DManager::D3DManager() 
    { 
     exitev = CreateEvent(NULL, true, false, NULL); 
     hthread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL); 
     _OutputDebugString("D3DManager: thread created handle %x\n", hthread); // my wrapper around OutputDebugString 

    } 

    D3DManager::~D3DManager() 
    { 
     stop(); 
     HRESULT hr = WaitForSingleObject(hthread, 1000); 
     if (hr == WAIT_ABANDONED) { 
      TerminateThread(hthread, 0); 
      release_d3d(); 
     } 
     CloseHandle(exitev); 
    } 

    unsigned int __stdcall D3DManager::thread(void *) 
    { 
     create_d3d9(); 
     while(!exit_signal()) { 
      WaitForSignleObject(exitev, 500); 
      d3.lock(); 
      HRESULT hr = g_d3ddev->TestCooperativeLevel(); 
      switch(hr) { 
       case S_OK: 
         break; 
       case D3DERR_DEVICENOTRESET : 
         // Fill DISPLAYPARAMETERS 
         g_d3ddev->Reset(); 
         break; 
       default: 
         break; 
      } 
      d3.unlock(); 
     } 

    ///////// This text is never seen 

     OutputDebugString("D3dManagert exit from while loop\n"); 

    //////// 
     release_d3d(); 
     _endthreadex(0); 
     return 0; 
    } 

내 구성 요소가 C#에서 작성된 WindowsForms 양식에 포함되어 있습니다.

문제는 양식을 닫을 때 스레드가 루프 동안 종료되고 그 후에 코드에 도달하지 않는다는 것입니다. OutputDebugString에서 텍스트를 본 적이 없으며 release_d3d()도 호출되지 않으며 메모리 누수에 대한 d3d 디버그 메시지가 많이 표시됩니다. 중단 점을 설정하면 절대 중단되지 않습니다.

내가 보는 모든

는 메시지입니다 : 내가 소멸자에서 중단 점을 설정

The thread 'Win32 Thread' (0x1044) has exited with code 0 (0x0) 

, 나는 그것을 명중 얻을 수 있지만, 비디오 메모리 누수에 대한 메시지 후.

Studio에서 C++ 예외 및 Win32 예외에 디버그 중단을 설정했지만 트리거 된 것도 없습니다.

업데이트. 모든 스레드가 그 중 하나가 exit 호출 할 때, _exit, 또는 abort 또는 ExitProcess을 종료하고 생성자 atexit 핸들러에 stting입니다 시도하는 MSDN에서 읽고 : 아직도

D3DManager::D3DManager() 
    { 
     exitev = CreateEvent(NULL, true, false, NULL); 
     hthread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL); 
     _OutputDebugString("D3DManager: thread created handle %x\n", hthread); 
     atexit(&release_d3d); 
    } 

행운. 비디오 메모리 누수에 대한 메시지를받은 후에 release_d3d이 호출됩니다. 게다가 나는 예외적 인 잘못을 가지고있다.

다음 업데이트 2.

// .h 
class D3DManager { 
    static mutex d3; // mutex is my own class, just a wrapper around CriticalSection 
    static LPDIRECT3D9 g_d3d; 
    static LPDIRECT3DDEVICE9 g_d3ddev; 
    static D3DPRESENT_PARAMETERS g_d3dpp; 
    static int g_d3d_counter; 
    static HANDLE hthread; 
    static HANDLE exitev; 

public: 
    D3DManager(); 
    ~D3DManager(); 

    static unsigned int __stdcall thread(void *); 
    static void stop(void) { SetEvent(exitev); } 

    static void CreateD3DDevice(LPDIRECT3D9& d3dobj, LPDIRECT3DDEVICE9& d3ddev); 
    static void DestroyD3DDevice(void); 
    static void GetSwapChain(HWND hwnd, LPDIRECT3DSWAPCHAIN9& chain); 
    static void release_d3d(void); 
    static void LockDevice(void) { d3.lock(); }; 
    static void UnlockDevice(void) { d3.unlock(); }; 
}; 



//.cpp 

        mutex D3DManager::d3; 
       LPDIRECT3D9 D3DManager::g_d3d = NULL; 
     LPDIRECT3DDEVICE9 D3DManager::g_d3ddev = NULL; 
    D3DPRESENT_PARAMETERS D3DManager::g_d3dpp; 
         int D3DManager::g_d3d_counter = 0; 
        HANDLE D3DManager::hthread; 
        HANDLE D3DManager::exitev; 

      // this variable will be single and shared by all activeX instances 
      static D3DManager d3dm; 


    D3DManager::D3DManager() 
    { 
     exitev = CreateEvent(NULL, true, false, NULL); 
     hthread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL); 
     _OutputDebugString("D3DManager: thread created handle %x\n", hthread); // my wrapper around OutputDebugString 

    } 

    D3DManager::~D3DManager() 
    { 
     stop(); 
     HRESULT hr = WaitForSingleObject(hthread, 1000); 
     if (hr == WAIT_TIMEOUT) { 
      TerminateThread(hthread, 0); 
      release_d3d(); 
     } 
     CloseHandle(exitev); 
    } 

    unsigned int __stdcall D3DManager::thread(void *) 
    { 
     create_d3d9(); 
     while(WAIT_TIMEOUT == WaitForSingleObject(exitev, 500)) { 
      d3.lock(); 
      HRESULT hr = g_d3ddev->TestCooperativeLevel(); 
      switch(hr) { 
       case S_OK: 
         break; 
       case D3DERR_DEVICENOTRESET : 
         // Fill DISPLAYPARAMETERS 
         g_d3ddev->Reset(); 
         break; 
       default: 
         break; 
      } 
      d3.unlock(); 
     } 

    ///////// This text is never seen 

     OutputDebugString("D3dManagert exit from while loop\n"); 

    //////// 
     release_d3d(); 
     _endthreadex(0); 
     return 0; 
    } 

답변

0

왜 정지 객체에서 대기하고 신호이라면, 여전히 코드 본문을 수행 편집 코드? 시도해보십시오.

while(WAIT_TIMEOUT==WaitForSingleObject(exitev, 500){ 
.. 
} 

도, 나는 그게 뭔지 모르겠다! exit_signal() 및 exit_mutex가 무엇입니까? 왜 뮤텍스가 필요한가요? 아니면 이미 신호를 보낼 이벤트가있을 때 exit boolean입니까? 멈추는 것보다 다른 이유로 이벤트를 알리는 코드가 더 있습니까? WFSO - 'WaitForSignleObject'를 입력 했으므로 실제 코드를 게시하지 않았습니다.

'(hr == WAIT_ABANDONED)'에 대해서도 언급하지 않습니다.나는 스레드가 종료 될 때까지 기다릴 필요가 없으므로 스레드 핸들을 기다릴 때 그 리턴이 만들어 지는지 확실히 알지 못한다.

+0

네 말이 맞아요. 코드를 단순화하고 exit_mutex 및 exit_flag를 제거 할 수 있습니다. – wl2776

+0

WAIT_ABANDONED는 뮤텍스에서 대기 중일 때도 발생합니다. 그래서, 분명히 2 가지 오류가 있습니다. 나는 진짜 코드를 올렸지 만, 그것들 모두가 카피 된 + 붙여 넣기가 아니고, 손으로 타이핑했다. :) – wl2776

0

exit_signal()이 값을 복사하지만 반환하지는 않습니다. 동기화 된 코드 블록을 벗어난 후 변수 exit_flag가 변경되고 exit_signal()이 false를 반환 할 가능성이 있습니다.

+0

Oups, 네, 맞아. 어쨌든 필자는이 기능을 제거 했으므로 필자는 더 이상 필요하지 않습니다. 수정 된 코드는 질문 하단에 있습니다. – wl2776

관련 문제