win32线程意外终止在activeX(C++)
我正在开发一个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;
}
为什么要等待停止对象,然后,如果信号,仍然执行代码的身体吗?尝试
while(WAIT_TIMEOUT==WaitForSingleObject(exitev, 500){
..
}
也,我不知道所有的!exit_signal()和exit_mutex是?为什么你需要一个互斥体,或者,在这种情况下,当你已经有一个事件发出信号时,你需要一个退出布尔值?是否还有其他一些代码可以通过其他原因发出信号而不是停止?我注意到你有错误的WFSO - 'WaitForSignleObject',所以你没有发布你的真实代码。
不是起诉'if(hr == WAIT_ABANDONED)'。我几乎没有等待线程终止,所以我不确定是否/为什么在等待线程句柄时返回。
我看到你的exit_signal()复制了这个值,但是没有返回它。退出同步代码块后,可能会有变量exit_flag被更改,并且exit_signal()返回false。
Oups,是的,你是对的。无论如何,我已经删除了这个功能,因为我不再需要它了。更正的代码位于问题的底部 – wl2776 2012-04-11 08:00:16
是的,看起来你是对的,我可以简化我的代码并摆脱exit_mutex和exit_flag。 – wl2776 2012-04-11 07:33:22
WAIT_ABANDONED也是在互斥体上等待时产生的。所以,显然有2个错误。我已经发布了一个真实的代码,但并不是所有代码都被复制+粘贴,我用手输入了它:) – wl2776 2012-04-11 07:47:18