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;
}
네 말이 맞아요. 코드를 단순화하고 exit_mutex 및 exit_flag를 제거 할 수 있습니다. – wl2776
WAIT_ABANDONED는 뮤텍스에서 대기 중일 때도 발생합니다. 그래서, 분명히 2 가지 오류가 있습니다. 나는 진짜 코드를 올렸지 만, 그것들 모두가 카피 된 + 붙여 넣기가 아니고, 손으로 타이핑했다. :) – wl2776