如何处理Qt中另一个线程的信号泛洪

时间:2013-04-20 13:44:04

标签: c++ multithreading qt video-streaming kinect

tl; dr:我有一个QThread,只要有新数据可供处理,它就会向主线程发送信号。然后主线程获取,处理和显示数据。数据更频繁地到达主线程能够处理它导致冻结的GUI并最终堆栈溢出(yay!)。

详情

我的应用程序从相机获取帧以进行处理和显示。相机通过Windows事件通知新帧何时可用。我有一个线程,它定期检查这些事件,并在新框架可用于抓取时通知主线程:

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()之间运行:

void Camera::onNewColorFrame()
{   
    worker_->blockSignals(true)
    getFrameFromCamera();
    processFrame();
    drawFrame();
    QCoreApplication::processEvents(); // this is essential for the GUI to remain responsive
    worker_->blockSignals(false);
}

这看起来是一种很好的方式吗?有人可以提出更好的解决方案吗?

1 个答案:

答案 0 :(得分:2)

我认为在您解决技术方面之前,您应该考虑考虑应用程序的设计方面。有几种方法可以解决您的问题,但首先您应该决定如何处理您没有时间在主线程中处理的帧。您是要跳过它们还是保存以供以后处理,但是您应该意识到处理队列仍然必须具有一定的大小限制,因此您无论如何都应该决定如何处理“越界”数据。

我个人更喜欢在这种情况下制作一些容纳某处的数据的中间容器,因此您的相机处理线程只是通知收集器收到的数据和收集器决定是否要存储或跳过数据。主循环,只要它具有fetchNext()或fetchAll()形式的时间访问收集器,具体取决于您的需要并实现对象处理。