0

我正在使用HANDLES,第一个nextColorFrameEvent是事件处理程序,第二个是流处理程序。它们在以下代码中被初始化:

nextColorFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
hr = nui->NuiImageStreamOpen(
            NUI_IMAGE_TYPE_COLOR,
            NUI_IMAGE_RESOLUTION_640x480,
            0,
            2,
            nextColorFrameEvent,
            &videoStreamHandle);

我想在销毁时妥善处理它们,同时不产生错误。有时初始化程序不会被调用,因此当软件结束时,两个 HANDLE 仍然为 NULL。这就是为什么我想首先检查 HANDLE 是否已正确初始化等,如果是,我想关闭它们。为此,我得到了以下代码:

    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

我需要不同的函数来关闭流处理程序吗?

4

4 回答 4

3

nui->NuiImageStreamOpen(...)不会为流创建有效的 Windows 句柄,而是在驱动程序端创建一个内部句柄。
所以你不能使用windows API来释放/关闭流句柄!!!

  • 为此,只需调用nui->NuiShutdown(). 我还没有使用回调事件,但我认为它是一个有效的窗口句柄,应该正常关闭。
  • 如果您只需要更改设置,您可以随时调用nui->NuiImageStreamOpen(...)新设置。无需关机...
  • 我也欢迎功能nui->NuiImageStreamClose(...);,因为API的当前状态会使长期运行的应用程序的事情变得复杂,因为传感器配置会发生变化。
于 2013-11-08T08:31:37.813 回答
1

如果未创建事件,则CreateEvent ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx ) 返回 NULL。

您正在检查不为 NULL 的 INVALID_HANDLE_VALID。

于 2013-05-03T12:19:38.870 回答
1

您可能正在尝试双重关闭句柄。那很可能会产生ERROR_INVALID_HANDLE 6. 您无法通过测试检测到这一点,因为第一个CloseHandle(nextColorFrameEvent);没有改变nextColorFrameEvent

解决方案是使用 C++ 技术,尤其是 RAII。关于如何使用shared_ptrwith有很多例子HANDLEshared_ptr是在每个人都完成后最多运行一次清理代码的标准解决方案,并且只有在任何人实际分配了资源的情况下。

于 2013-05-03T13:34:03.483 回答
0

有一种我特别喜欢的调试的好方法,尽管都是用宏编写的,这很讨厌,但在这种情况下它们可以创造奇迹。

Zed 很棒的调试宏

不过,有几件事我喜欢改变。他们广泛使用 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());

如您所见,GetLastError 仅在 pRSemaphore 设置为 null 时调用。宏背后有一些花哨的机制(至少它们对我来说很花哨),但它们隐藏在“检查”掩码中,所以你不必担心它们。

下一步是使用以下内容处理错误:

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(); }

希望我能帮上忙

于 2014-11-15T12:51:35.190 回答