【发布时间】:2020-11-25 14:33:10
【问题描述】:
我只是尝试使用 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; }
我更喜欢任何其他选项,因为我宁愿在程序完成后不在程序中保留打印语句。我希望我的代码看起来像其他似乎不起作用的选项一样干净整洁。
如果有另一个更优雅的选择,我愿意改变它,我只需要一个有效且看起来干净的解决方案。
【问题讨论】:
-
任何体面的编译器都会看到它是一个无操作循环并优化它,因为它永远不需要执行。 (不执行任何操作的代码如果被删除,则对代码没有影响,因为……好吧,它是什么也不执行的代码。)
-
即使它没有被编译出来,你可能也不希望那里有一个消耗 CPU 的繁忙自旋循环,所以我将 print 语句替换为短时睡眠以释放 CPU做一些有用的事情。
-
睡眠是我正在考虑的事情,但我不知道这个项目的未来可能会怎样,而且我不想睡觉,不管它有多快成为任何瓶颈的原因。我在下面使用信号量提到了我的解决方案。
-
您的代码包含数据竞争:一个线程修改
captureComplete,而另一个线程正在读取它。这在 C++ 中是不合法的。 C++ 要求对共享变量的多线程访问受同步保护或声明为atomic。
标签: c++ winapi while-loop mutex static-members