【发布时间】:2013-04-13 11:39:32
【问题描述】:
我正在开发一个使用 Qt 的程序,我的一些代码基于 Windows 示例。我遇到的问题,我不太明白的问题是,相同的代码将如何阻止我的 Qt GUI,而它在 Windows 应用程序中完全可以正常工作。
这是一个例子。我有一个程序,它从相机获取一些数据,对其进行一些处理,然后将其显示在屏幕上。在 Windows 示例中有这样的内容:
// Create an event with these self-explanatory parameters
// This event signals when the next frame is ready to process
HANDLE frameEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)
// Now run a while loop which magically doesn't block
HANDLE hEvents[1];
while (WM_QUIT != msg.message)
{
hEvents[0] = frameEvent;
DWORD dwEvent = MsgWaitForMultipleObjects(1, hEvents, FALSE, INFINITE, QS_ALLINPUT);
// If we have our event run some processing
if (WAIT_OBJECT_0 == dwEvent)
{
update();
}
// Else handle input or whatever
}
更新函数如下所示:
if (WAIT_OBJECT_0 = WaitForSingleObject(frameEvent, 0)
{
getTheFrame();
processTheFrame();
drawTheFrame();
}
如果我尝试在 Qt 中以相同的方式实现它,一切都会冻结,while 循环将永远运行。我的解决方案是在单独的线程(QThread)中运行循环并在新帧准备好时发出信号,如下所示:
void Worker::run()
{
running_ = true;
while (running_)
{
if (WaitForSingleObject(frameEvent, 0) == WAIT_OBJECT_0)
{
emit signalFrame();
}
// This is necessary or it will still freeze!
usleep(15);
}
}
然后将信号连接到与 windows 示例中的 Update() 方法执行类似工作的插槽。
现在,这可以正常工作,但只要在下一帧可用之前处理单个帧即可。
随着我的处理变得更复杂并且比相机帧速率更慢,程序停止响应。 windows 示例中完全相同的代码仍然可以正常工作,帧率只是下降,但所有内容都已绘制并且 GUI 保持响应。
有人可以解释发生了什么吗?可能的解决方案是什么?
【问题讨论】:
-
您实际上替换了 Qt 消息循环,消息现在由 MWFMO 发送。我不知道 Qt 的消息循环是什么样的,但它肯定是非标准的。因此,事故并非不可能。不要发出信号,而是使用 PostMessage,这样帧检索代码仍然在主线程上运行。并使用一个事件来通知线程在检索到帧后恢复循环。
-
帧检索代码确实在主线程中运行。工作线程定期检查偶数,并在准备好检索新帧时发出信号。我不确定 Qt 的消息循环是否真的被替换了。问题在于相机每秒产生 30 帧,但我只能处理 10 帧。所以在我处理完一帧之前,已经有几帧可用了。暂停循环似乎是一个简单的解决方案(它在 Windows 上是如何工作的?在处理发生时帧是否刚刚丢弃?)。我设法通过使用使其工作
-
QThread::blockSignals()。所以它现在类似于 `onNewFrameReady() { worker.blockSignals(true);做处理(); worker.blockSignals(false); }。我猜使用信号暂停然后恢复循环会产生相同的效果。如果您愿意对此发表评论作为答案,我会接受它作为解决方案。
标签: c++ multithreading qt winapi loops