我正在開發一個ActiveX視頻播放器。它是DLL中的進程內組件。我正在使用Visual Studio 2010.我需要它有一個單獨的線程,它會在組件加載時創建一次,創建Direct3D9對象和Direct3D9設備,然後停止組件卸載並銷燬這些對象。在組件正在運行時,我希望此線程定期調用TestCooperativeLevel
,並在需要時重置D3D設備。win32線程意外終止在activeX(C++)
我這樣做是因爲客戶端應用程序可以創建我的播放器的幾個實例,但強烈建議只有一個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;
}
我的組件嵌入在WindowsForms窗體中,在C#中進行了寫入。
問題是,當我關閉窗體時,線程終止內部while循環和之後不會繼續執行代碼。我從來沒有見過OutputDebugString
的文本,release_d3d()
也從來沒有被調用過,並且我看到很多來自d3d調試的關於內存泄漏的消息。如果我設置了一個斷點,它永遠不會被擊中。
我看到的是消息:
The thread 'Win32 Thread' (0x1044) has exited with code 0 (0x0)
當我設置一個斷點在析構函數,我得到它擊中,但有關視頻內存泄漏的消息後。
我還啓用了C++異常和Win32異常在Studio調試中斷,但沒有被觸發。
更新。 在MSDN讀過的所有線程終止,當其中任何一個來電exit
,_exit
或abort
或ExitProcess
並在構造atexit
處理程序試圖stting:
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 2012-04-11 07:33:22
WAIT_ABANDONED也是在互斥體上等待時產生的。所以,顯然有2個錯誤。我已經發布了一個真實的代碼,但並不是所有代碼都被複制+粘貼,我用手輸入了它:) – wl2776 2012-04-11 07:47:18