3

tl;dr: 新しいデータを処理できるようになるたびにメイン スレッドにシグナルを送信する QThread があります。次に、メイン スレッドがデータを取得、処理、表示します。データが到着する頻度が高くなり、メイン スレッドがそれを処理できるため、GUI がフリーズし、最終的にスタック オーバーフローが発生します (イェイ!)。

詳細

私のアプリケーションは、処理と表示のためにカメラからフレームを取得します。カメラは、Windows イベントを通じて新しいフレームが利用可能になると通知します。これらのイベントを定期的にチェックし、新しいフレームが取得可能になったときにメイン スレッドに通知するスレッドがあります。

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

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

        usleep(15);
    }
}

signalColorFrameCameraカメラからフレームを取得し、何らかの処理を行い、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);
}

それはそれを行う良い方法のように見えますか?誰かがより良い解決策を提案できますか?

4

1 に答える 1

2

技術面を解決する前に、アプリケーションの設計面について考える必要があると思います。問題を解決する方法はいくつかありますが、最初に、メイン スレッドで処理する時間がないフレームをどうするかを決定する必要があります。それらをスキップするか、後で処理するために保存しますが、処理キューにはまだ特定のサイズ制限が必要であることを認識する必要があるため、とにかく「範囲外」データをどうするかを決定する必要があります。

このような場合、個人的には、どこかで受信したデータを保持する中間コンテナーを作成することをお勧めします。そのため、カメラ処理スレッドは、データを受信したことをコレクターに通知し、コレクターはデータを保存するかスキップするかを決定します。そして、必要に応じて fetchNext() または fetchAll() の形式でコレクターにアクセスし、オブジェクト処理を実装します。

于 2013-04-20T13:49:21.530 に答える