2016-05-24 15 views
1

私は、カメラから画像を連続的に読み込み、これをユーザーに表示するアプリケーションを持っています。ユーザーは、露出やしきい値などのさまざまなスライダを調整して、画像をリアルタイムで変更することができます。また、GUIの応答が遅くなることがあるので、このイメージを計算しています。そのため、スレッドを使用してワークロードを分割することにしました。Qt GUIでスレッドを使う方法

しかし、私はそれが正しく動作するようにすることができません、時々私はセグメンテーションフォールトと "アサーション" GLib-GObject-CRITICAL **の束を得ます:g_object_unref:アサーション 'G_IS_OBJECT(オブジェクト)'スライダーの値が変更されたり、画像を保存しようとすると(GUIにボタンを保存する)、GUIが画像の更新やフリーズを停止することがあるため、スライダーを移動したりボタンを押すことができません。

私がしようとしたのは、標準のstd :: threadをC++で使用し、それをスロットからスタートボタンに接続することでした。ユーザーは、彼らが私のマネージャーで変数を変更するスライダー値captureImageとProcessImagesが使用している(上記mngr)を変更

QObject::connect(btnStart, SIGNAL(clicked()), this, SLOT(RunStartThread())); 

void MainMenu::RunStartThread(){ 
std::thread t1; 
t1= std::thread(&MainMenu::Start,this); 
t1.detach(); 
} 

void MainMenu::Start() { 
run = true;  
    window->mngr->ReadCalibration(); 
    window->mngr->InitializeCameras(); 

    while (run) { 

     window->mngr->CaptureImage(); 
     window->mngr->ProcessImages();    
     UpdateLabels(); 
     } 

window->mngr->Stop(); 
} 

。変数をアクセスする際にstd :: mutex lock/unlockを使ってみましたが、何も変更されませんでした。私はこれをオンラインで行う方法の例を見つけようとしましたが、連続したwhileループを持つものはまだ見つけていません。

私はスレッドに関しては初心者ですので、間違った方法でこれに近づいているかどうか教えてください。

+2

[QThread](http://doc.qt.io/qt-5/qthread.html)を使うのがよいでしょうか? – someoneinthebox

+0

あなたのmngrインスタンスの機能はQTウィジェットに直接アクセスしないことを願っています。 2番目のスレッド(UpdateLabels()?)内からGUIの変更を行うには、signal/slot経由で行う必要があります。 – Aconcagua

+0

スライダからの更新はsignal/slotによって管理され、マネージャはQtウィジェットにアクセスできません。 GUIにはマネージャへの接続がありますが、逆の方法ではありません。 UpdateLabelsは単にマネージャからいくつかの画像情報を取得し、GUIのラベルを更新します。申し訳ございません。 私はQthreadを調べようとしましたが、それを行う方法の良い例は見つかりませんでした。 – user3518432

答えて

1

まず、スレッド間通信では、すべてシングナルとスロットを使用します。デフォルトでは、Qt接続はスレッド間でスレッドホッピングを行い、複雑な同期を避けることができます。

第2に、スレッドを使用する3つの方法があります。QThreadQRunnableQtConcurrent::Run(私のお気に入り、最小限のコードが必要です)。

ケースQThreadサブクラス化しないでください! common design mistakeです。

例:

SomeClass::~SomeClass() 
{ 
    SignalStop(); 
    future.result(); 
} 

void SomeClass::RunStartThread(){ 
    future = QtConcurrent::run(this, &SomeClass::DoOnThread); 
} 

void SomeClass::DoOnThread() 
{ 
    while (ShouldContinueToRun()) { 
     QImage im1 = CaptureImage(); 
     emit ImageCaptured(im1); 
     QImage im2 = ProcessImages(im1);    
     emit ImageProcessed(im2); 
    } 
    emit JobCompleted(); 
} 

QObject::connectは、別のスレッドが関与している場合は、スロットの呼び出しが実行される方法を定義する最後の引数を持っていることに注意してください。この引数にはdocumentation of enumerationを参照してください。
デフォルトでは、Qtはスレッドホッピングが必要かどうかを検出します。慎重にQObject::moveToThreadを読んでも問題を理解するのに役立つはずです(親があれば別のスレッドにオブジェクトを移動することはできません)。

+0

あなたのリンクに従えば、あなたの例で 'SomeClass'は' QThreadPool'から継承しなければなりませんか?むしろ 'doOnThread'が静的で、パラメータ' SomeClass * 'を持ち、' ​​run(&doOnThread、this); 'を呼び出すと思います。私は何を取りこぼしたか? – Aconcagua

+0

画像がopencvのimshowを使って表示されている場合は、イメージがキャプチャされたという信号を放射する必要がありますか? updatelabelsはこれに依存しているので、処理しました。しかし、その信号をupdateLabels()関数/スロットにどのように接続すればよいでしょうか? JobCompletedと同じですが、この信号を自分の関数にどのように結び付けるのですか? – user3518432

+0

@Aconcagua [この文書の部分](http://doc.qt.io/qt-5/qtconcurrentrun.html#using-member-functions)を参照してください。 – thuga

関連する問題