C++ 如何在Qt中处理来自另一个线程的信号溢出

C++ 如何在Qt中处理来自另一个线程的信号溢出,c++,multithreading,qt,video-streaming,kinect,C++,Multithreading,Qt,Video Streaming,Kinect,tl;dr:我有一个QThread,每当有新数据可供处理时,它就会向主线程发送一个信号。然后,主线程获取、处理和显示数据。当主线程能够处理数据时,数据到达的频率会更高,导致GUI冻结,最终导致堆栈溢出(耶!) 详细信息 我的应用程序从相机获取帧以进行处理和显示。相机通过windows事件通知新帧何时可用。我有一个线程,它定期检查这些事件,并在新帧可用于抓取时通知主线程: void Worker::run() { running_ = true; while (running_)

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

详细信息

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

void Worker::run()
{
    running_ = true;

    while (running_)
    {
        if (WaitForSingleObject(nextColorFrameEvent, 0) == WAIT_OBJECT_0)        
            emit signalColorFrame();        

        usleep(15);
    }
}
signalColorFrame
连接到
Camera
类中的一个插槽,该插槽从Camera获取帧,进行一些处理并将其发送到
MainWindow
并将其绘制到屏幕上

void Camera::onNewColorFrame()
{    
    getFrameFromCamera();
    processFrame();
    drawFrame();
}
现在,如果该方法在下一帧可用之前完成,则一切正常。随着处理变得越来越复杂,尽管
摄影机
类在处理前一帧之前接收到新信号

我的解决方案是在处理期间阻止来自工作线程的信号,并使用
QCoreApplication::processEvents()


这看起来像是一个好方法吗?有人能提出一个更好的解决方案吗?

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


在这种情况下,我个人更愿意制作一些中间容器,其中保存在某处接收到的数据,所以您的相机处理线程只需通知收集器接收到的数据,收集器就可以决定是存储还是跳过数据。和主循环,只要它具有形式为fetchNext()或fetchAll()的time access collector,这取决于您需要什么并实现对象处理。

好的,我删除了关于此解决方案不可靠的部分,因为这是由于我的错误。它基本上是按预期工作的。是的,我一直在考虑这个问题。他们目前的工作方式就是在最后一个帧被处理之前不接受新帧,然后得到当前可用的帧(所以是最新的帧)。这是用于实时数据的。我还将进行离线处理,类似于您建议的解决方案将更合适。这样,我认为您根本不需要发出信号。为什么你应该通知自己决定的事情,然后它有处理时间。因此,与其发送信号并传递将被丢弃的应用程序数据,不如将最新帧存储在摄影机对象中,并使用线程安全的方法,如getLatestFrame(),这样主线程在没有作业时就会检查摄影机是否有要处理的内容…工作线程只发送新帧可用性的信号,它不传递任何数据。数据在主线程中检索(即Caera对象生命)。我之所以需要一个工作线程,是因为循环不断地检查是否发生了事件,否则会阻塞GUI。那么,我会发布事件,而不是发出信号。出于不同的原因,我认为在线程之间发送信号不是一个好主意。至少使用排队连接类型。(但这实际上是事件的信号/插槽机制包装)我不知道如何在Qt中处理事件。如果我发布事件,我如何在没有消息循环的情况下处理它?
void Camera::onNewColorFrame()
{   
    worker_->blockSignals(true)
    getFrameFromCamera();
    processFrame();
    drawFrame();
    QCoreApplication::processEvents(); // this is essential for the GUI to remain responsive
    worker_->blockSignals(false);
}