检查和关闭手柄

时间:2013-05-03 12:16:03

标签: c++ windows handle

我正在使用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函数来关闭流处理程序?

4 个答案:

答案 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_ptrHANDLE一起使用的示例。 shared_ptr是在每个人完成后最多只运行一次清理代码的标准解决方案,并且只有在任何人实际分配了资源时才会这样做。

答案 3 :(得分:0)

有一种很好的调试方式我特别喜欢,尽管它们都是用宏编写的,这些都是令人讨厌的,但在这种情况下它们会产生奇迹。

Zed's Awesome Debug Macros

我想改变一些事情。他们广泛使用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(); }
希望我能得到任何帮助