首页 > 解决方案 > 为什么当我在其中什么都不做(不做任何循环)时,我的 while 循环不起作用?

问题描述

我只是试图使用一个while循环来帮助控制我的程序的每秒帧数,该程序显示实时摄像机源以及与摄像机正在查看的数据相对应的数据。这不是微不足道的原因是因为调用的循环getFramesAfterCapture()运行速度比相机获取图像的速度快得多(因为它是在收集当前帧和需要显示的数据的更新方法中调用的)。

我的想法是让这个函数像使用互斥锁一样简单地等待,直到不再满足我的 while 循环中的条件。回调在另一个线程中运行,并且captureComplete是类的静态成员变量,因此它是它的唯一实例。当从我的相机捕获帧的回调完成捕获新图像时,此 bool 的值会发生变化。必须以这种方式完成,因为我需要将显示到屏幕的数据与帧的捕获同步,这样数据和视频显示匹配。

这是我的代码:

    long CALLBACK FrameGrabber::destCallback(LPVOID lpUser, LPVOID lpReserved) {
        // copy the data into the bitmap
        if (WaitForSingleObject(hMutex, 10) == WAIT_OBJECT_0)
        {
            DWORD dwSize = VIDEO_SIZE;
            //get bitmap
            dpGetSurfaceData(hDest, bitmap + sizeof(BITMAPINFOHEADER), &dwSize);
    
            ReleaseMutex(hMutex);
            // set capture to complete so that waitForCapture releases from the do-nothing loop
            WaitForSingleObject(captureCmpltMutex, INFINITE);
            captureComplete = true;
            ReleaseMutex(captureCmpltMutex);
        }
        
        return 0;
    }
    
    BYTE* FrameGrabber::getFrameAfterCapture() {
        // loop while capture is still not completed
        ////while (!captureComplete);
        while (!captureComplete) { 
            std::cout << "Waiting for capture to complete..." << std::endl;
        }
    
        //std::cout << "Capture Complete!" << std::endl;
        // when capture is completed set captureComplete back to false so that this waits again until the next frame is acquired
        WaitForSingleObject(captureCmpltMutex, INFINITE);
        captureComplete = false;
        ReleaseMutex(captureCmpltMutex);
    
        return bitmap;
    }

我的循环工作正常,因为它是......

    while (!captureComplete) { 
        std::cout << "Waiting for capture to complete..." << std::endl;
    }

但是当我将其更改为此时不起作用...

    while (!captureComplete);

或这个...

    while (!captureComplete) { }

或这个...

    while (!captureComplete) continue;

或这个...

    while (!captureComplete){ continue; }

我更喜欢其他任何选项,因为我宁愿在程序完成后不在程序中保留打印语句。我希望我的代码看起来像其他似乎不起作用的选项一样干净整洁。

如果有另一个更优雅的选择,我愿意改变它,我只需要一个有效且看起来干净的解决方案。

标签: c++winapiwhile-loopmutexstatic-members

解决方案


我能够使用二进制信号量而不是互斥锁或静态成员布尔值找出更优雅的解决方案。使用互斥锁和二进制信号量的区别在于,二进制信号量不需要我在 getFrameCapture() 结束时释放信号量。基本上,当一个信号量被释放时,它持有的计数加一。相反,当等待函数返回时,信号量持有的计数减一。

这允许信号行为,如果我在开始时等待互斥锁并在 getFrameCapture() 方法返回等待捕获帧的函数的整个点之前释放它,则会丢失。同样,如果我在函数返回之前不释放它,互斥锁将返回 WAIT_ABANDONED 告诉程序员线程意外退出并且互斥锁已被它放弃。

溶胶:

long CALLBACK FrameGrabber::destCallback(LPVOID lpUser, LPVOID lpReserved) {
    // copy the data into the bitmap
    if (WaitForSingleObject(hMutex, 10) == WAIT_OBJECT_0)
    {
        DWORD dwSize = VIDEO_SIZE;
        //get bitmap
        dpGetSurfaceData(hDest, bitmap + sizeof(BITMAPINFOHEADER), &dwSize);

        ReleaseMutex(hMutex);
        //Release semaphore (emit signal)
        ReleaseSemaphore(captureCmpltSemaphore, 1, NULL);
    }
    
    return 0;
}

BYTE* FrameGrabber::getFrameAfterCapture() {
    //Wait for semaphore to be released (Signaled)
    WaitForSingleObject(captureCmpltSemaphore, INFINITE);
    //return bitmap
    return bitmap;
}

我参考了这个链接来找到我的解决方案: https ://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasesemaphore


推荐阅读