![](/img/trans.png)
[英]How to update the Qt GUI from a Boost signal that is raised in another thread?
[英]How to handle signal flood from another thread in Qt
tl; dr:我有一个QThread,只要有新数据可供处理,它就会向主线程发送信号。 然后主线程获取,处理和显示数据。 数据更频繁地到达主线程能够处理它导致冻结的GUI并最终堆栈溢出(耶!)。
细节
我的应用程序从相机获取帧以进行处理和显示。 相机通过Windows事件通知新帧何时可用。 我有一个线程,它定期检查这些事件,并在新帧可用于grabs时通知主线程:
void Worker::run()
{
running_ = true;
while (running_)
{
if (WaitForSingleObject(nextColorFrameEvent, 0) == WAIT_OBJECT_0)
emit signalColorFrame();
usleep(15);
}
}
signalColorFrame
连接到Camera
类中的一个插槽,该插槽从相机获取帧,进行一些处理并将其发送到MainWindow
,将其绘制到屏幕上。
void Camera::onNewColorFrame()
{
getFrameFromCamera();
processFrame();
drawFrame();
}
现在如果该方法在下一帧可用之前完成,一切正常。 由于Camera
类在处理前一帧之前接收到新信号,因此处理变得更加复杂。
我的解决方案是在处理时阻止来自工作线程的信号,并强制使用QCoreApplication::processEvents()
在其间运行even循环:
void Camera::onNewColorFrame()
{
worker_->blockSignals(true)
getFrameFromCamera();
processFrame();
drawFrame();
QCoreApplication::processEvents(); // this is essential for the GUI to remain responsive
worker_->blockSignals(false);
}
这看起来像是一种很好的方式吗? 有人可以建议更好的解决方案?
我认为在您解决技术方面之前,您应该考虑考虑应用程序的设计方面。 有几种方法可以解决您的问题,但首先您应该决定如何处理您没有时间在主线程中处理的帧。 您是要跳过它们还是保存以供以后处理,但是您应该意识到处理队列仍然必须具有一定的大小限制,因此您无论如何应该决定如何处理“越界”数据。
我个人更喜欢在这种情况下制作一些容纳某处的数据的中间容器,所以你的相机处理线程只是通知收集器收到的数据和收集器决定它是存储还是跳过数据。 并且主循环只要它具有时间访问收集器的形式fetchNext()或fetchAll()取决于您需要并实现对象处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.