2013-04-20 59 views
3

TL;博士:我有一个QThread的当新数据可用于处理将信号发送到主线程。主线程然后获取,处理和显示数据。主线程可以更频繁地处理数据,导致冻结的GUI并最终导致堆栈溢出(yay!)。如何从另一个线程处理信号洪水的Qt

详细

我的应用程序获取帧从照相机,用于处理和显示。相机通过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); 
} 

不会看起来像做这件事的好方法吗?有人可以提出更好的解决方案吗

+0

好吧,我删除了这个解决方案是不可靠的零件,因为这是由于我的失误。它非常符合预期。 – jaho 2013-04-20 15:34:03

回答

2

我想你解决技术方面之前,你应该考虑考虑您的应用程序的设计方面。有几种方法可以解决您的问题,但首先您应该决定如何处理您没有时间在主线程中处理的帧。你要跳过或保存供以后处理,但你应该认识到,处理队列还必须有一定的规模限制,所以你应该反正决定如何处理“出界”的数据做。

我个人更喜欢在这种情况下,使持有并获得地方使用的数据,让你的相机处理线程只是通知接收到的数据和收藏家决定如果要存储或跳过数据收集一些中间容器。主循环只要有时间以fetchNext()或fetchAll()的形式访问收集器,具体取决于你需要什么并实现对象处理。

+0

是的,我一直在想这个。他们目前的工作方式就是不接受新的框架,直到最后一个框架被处理完毕,然后获得当前可用的框架(因此是最新的框架)。这是针对实时数据的。我也会进行离线处理,其中与您所建议的解决方案类似的解决方案将更合适。 – jaho 2013-04-20 15:39:10

+0

这样,我不认为你需要发出信号。为什么你应该通知一些决定自己的东西,然后它就有可用的处理时间。因此,而不是信令和横穿将被扔掉的应用程序数据是不是更好保存最新的框架在你的相机对象,使线程安全的方法,像getLatestFrame(),所以主线程,只要它没有工作将检查是相机有东西要处理... – evilruff 2013-04-20 15:42:34

+0

工作者线程只发出新的帧可用性信号,它不传递任何数据。数据在主线程中被检索到(这是Caera对象的生命)。我需要一个工作线程的原因是,循环不断检查事件是否发生,否则会阻塞GUI。 – jaho 2013-04-20 16:06:36