我正在使用HANDLES
,第一个,nextColorFrameEvent
是一个事件处理程序,第二个是流处理程序。它们正在以下代码中初始化:
nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
hr = nui->NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_640x480,
0,
2,
nextColorFrameEvent,
&videoStreamHandle);
我希望在销毁时妥善处理它们,同时不要同时创建错误。有时初始化程序不会被调用,因此当软件结束时,两个HANDLEs仍然是NULL。这就是为什么我要首先检查HANDLEs是否正确初始化等等,如果是,我想关闭它们。我得到了以下代码:
if (nextColorFrameEvent && nextColorFrameEvent != INVALID_HANDLE_VALUE)CloseHandle(nextColorFrameEvent);
#ifdef QT_DEBUG
DWORD error = GetLastError();
qDebug()<< error;
#endif
if (videoStreamHandle && videoStreamHandle != INVALID_HANDLE_VALUE)CloseHandle(videoStreamHandle);
#ifdef QT_DEBUG
error = GetLastError();
qDebug()<< error;
#endif
但这显然是不正确的:如果我不运行初始化程序然后关闭软件这段代码运行并给我一个6:
Starting C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController...
6
6
C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController exited with code 0
表示:
ERROR_INVALID_HANDLE 6(0x6)句柄无效。 这意味着尽管进行了测试,但closeHandle仍在运行。当手柄不是有效的手柄时,我应该做哪些测试来阻止关闭?
加分问题:如果我运行初始化程序,只关闭colorFrameEvent时将不再出现此错误,但在关闭videoStreamHandle时仍会出现:
Starting C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController...
0
6
C:\...\Qt\build-simpleKinectController-Desktop_Qt_5_0_2_MSVC2012_64bit-Debug\debug\simpleKinectController exited with code 0
我是否需要一个diffent函数来关闭流处理程序?
答案 0 :(得分:3)
nui->NuiImageStreamOpen(...)
不为流创建有效的Windows句柄,而是在驱动程序端创建内部句柄。
因此您无法使用Windows API来释放/关闭流处理!!!
nui->NuiShutdown()
。我还没有使用回调事件,但我认为它是一个有效的窗口句柄,应该正常关闭。 nui->NuiImageStreamOpen(...)
。无需关机...... nui->NuiImageStreamClose(...);
,因为 API 的当前状态会使传感器配置发生变化,从而使长期运行的aps变得复杂。答案 1 :(得分:1)
如果未创建事件,CreateEvent(http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx)将返回NULL。
您正在检查非NULL的INVALID_HANDLE_VALID。
答案 2 :(得分:1)
您可能正在尝试双关闭手柄。这很可能会产生ERROR_INVALID_HANDLE 6
。您无法通过测试检测到此问题,因为第一个CloseHandle(nextColorFrameEvent);
未更改nextColorFrameEvent
。
解决方案是使用C ++技术,特别是RAII。有很多关于如何将shared_ptr
与HANDLE
一起使用的示例。 shared_ptr
是在每个人完成后最多只运行一次清理代码的标准解决方案,并且只有在任何人实际分配了资源时才会这样做。
答案 3 :(得分:0)
有一种很好的调试方式我特别喜欢,尽管它们都是用宏编写的,这些都是令人讨厌的,但在这种情况下它们会产生奇迹。
我想改变一些事情。他们广泛使用goto,我倾向于避免,特别是在c ++项目中,因为否则你将无法在代码中声明变量。这就是我使用exit(-1)的原因,或者,在某些项目中,我修改代码来尝试,抛出,捕获c ++。由于您正在使用Handles,因此设置变量并告诉程序自行关闭是一件好事。
这就是我的意思。从宏中获取这段代码(我假设你会阅读练习并熟悉宏):
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
我要改变
goto error;
类似
error = true;
程序中的语法就像是,我从一个我自己编写的多线程程序中获取它:
pRSemaphore = CreateSemaphore(NULL, 0, MAX_TAM_ARQ, (LPCWSTR) "p_read_semaphore");
check(pRSemaphore, "Impossible to create semaphore: %d\n", GetLastError());
如您所见,仅当pRSemaphore设置为null时才会调用GetLastError。宏观背后有一些奇特的机制(至少它们对我来说很奇怪),但它们隐藏在“检查”面具中,所以你不必担心它们。
下一步是用以下内容处理错误:
inline void ExitWithError(bool &err) {
//close all handles
//tell other related process to do the same if necessary
exit(-1);
}
或者你可以在宏内部调用它,如
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; ExitWithError(); }
希望我能得到任何帮助