2013-04-20 83 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