2016-08-08 15 views
0

私は2つのクラスを持っています:AとBはどちらもQObjectからサブクラスです。2つのスレッドでmovetoThreadを使用して2つのQObject間でシグナルとスロットを接続する方法

class A:public QObject 
{ 
Q_OBJECT 
public: 
A(); 
~A(); 
} 

私はちょうどthis articleを参照しました。次に、GUIで (メインスレッドを言う)Iは

pA = new A(); 
QThread *workerThread = new QThread; 
pA->moveToThread(workerThread); 
connect(workerThread , SIGNAL(started()), pA, SLOT(doWork())); 
connect(pA, SIGNAL(finished()), workerThread , SLOT(quit())); 
connect(pA, SIGNAL(finished()), pA, SLOT(deleteLater())); 
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater())); 
workerThread ->start(); 
pB = new B(); 
connect(pA,SIGNAL(sigProduce(double)),pB,SLOT(slotConsume(double)));//I just don't know where to put this line 
QThread *workerThread = new QThread; 
pB ->moveToThread(workerThread); 
connect(workerThread , SIGNAL(started()), pB , SLOT(doWork())); 
connect(pB , SIGNAL(finished()), workerThread , SLOT(quit())); 
connect(pB , SIGNAL(finished()), pB , SLOT(deleteLater())); 
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater())); 
workerThread ->start(); 

sigProduce(二重)を用いて、異なるスレッドでAとBの間でデータを交換しようとするオブジェクトとslotConsume(二重)で定義された信号であります公共スロット:クラスBの ヘッダ:?

public slots: 
void slotConsume(double); 

ので、プログラムは、OBJのBは、誰も私を助けることができる(PA、PB)のコードの位置の問題を接続OBJ A.Doesから二重のデータを取得することはできません開始した後?感謝します。

+0

いいえ、いつ接続するかは関係ありません。実行時に接続のタイプが解決されます。コードの一部は正常に見えますが、完全なコードサンプルではありません。 SSCCEに問題を提出してください。 –

+0

あなたは 'QThread * workerThread = new QThread;'を2回持っています。同じ名前の変数を2回宣言することはできません。これはあなたの本当のコードですか? – thuga

+0

コードを見直したところ、各AまたはBオブジェクトのdoWork()関数でqApp-> processEvents()が必要であることがわかりました。私はBのdoWork()ループでそれを呼び出すことを忘れてしまいます。もう1つの重要なことは、いつcennect関数を呼び出すかは関係ありません。そして、これはSazonovが言ったことです。 – liyang

答えて

0

問題を解決する方法を詳しく説明する前に、最初に問題が有効であることを確認してください。スレッドを使用している唯一の理由は、無限ループが必要なためです。多分スレッドを必要としないかもしれません。ループ内の作業が軽い場合は、QTimerのメインスレッドで行うことができます。これについてもっと知るには、this articleを読んでください。

とにかく問題は、スレッドのイベントループをブロックしているdoWorkメソッドに無限ループがあるためです。このため、processEventsに電話する必要がありました。しかし、これは良いデザインではありません。より良い方法は、無限ループをdoWorkから削除することによってスレッドをイベントループに戻すことです。

これで、タイマーでループをシミュレートし、スレッドを停止したいときにタイマーを停止できます。またはQMetaObject::invokeMethodQt::QueuedConnectionを使用してイベントループからdoWorkメソッドを呼び出し、bool条件を使用して作業を停止することができます。この例では、invokeMethodオプションを使用しました。

#include <QCoreApplication> 
#include <QThread> 
#include <QTimer> 
#include <QDebug> 

class Worker : public QObject 
{ 
    Q_OBJECT 

public: 
    Worker(QObject *parent = 0) : QObject(parent), _stop(false) {} 

public slots: 
    void doWork() 
    { 
     if(_stop) 
      return; 
     QThread::sleep(1); // simulating some heavy work here 
     emit calculationComplete(1564); 
     QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection); 
    } 

    void stop() 
    { 
     _stop = true; 
    } 

signals: 
    void calculationComplete(int result); 

private: 
    bool _stop; 

}; 

class ResultHandler : public QObject 
{ 
    Q_OBJECT 
public: 
    ResultHandler(QObject *parent = 0) : QObject(parent) {} 

public slots: 
    void handleResult(int result) 
    { 
     // do something with result 
     qDebug() << Q_FUNC_INFO << "Result:" << result; 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    QThread thread_a; 
    Worker worker; 
    ResultHandler handler; 

    QObject::connect(&worker, &Worker::calculationComplete, &handler, &ResultHandler::handleResult); 
    QObject::connect(&thread_a, &QThread::started, &worker, &Worker::doWork); 
    QObject::connect(&thread_a, &QThread::finished, &worker, &Worker::stop); 

    worker.moveToThread(&thread_a); 
    thread_a.start(); 

    QTimer::singleShot(5000, &thread_a, &QThread::quit); // just simulating an exit 

    int result = a.exec(); 
    thread_a.quit(); 
    thread_a.wait(5000); 
    return result; 
} 

#include "main.moc" 
+0

ありがとうございました。私のアプリケーションはコンピュータビジョンフィールドにあり、私は現在2つのワーカースレッドを持っています.1つは画像を取得し、もう1つは処理しています。ほとんどの場合、システムはグラブと画像処理を行い、処理タスクは200 msごとに処理を終了します。この状況はあなたの方法に適していますか? – liyang

+0

私の計画を記述する必要があります...私は、カメラから非同期の画像を取得するために1つのQThreadを使用します(ここでは、同時に複数のカメラがあるので、同じ数のQThreadを実装する必要がありますか?)、resultHandler Objは、画像は画像処理と呼ばれます。 – liyang

+0

@liyang参照してください。次に、画像処理を新しいスレッドに確実に移行する必要があります。だから私の例では、 'doWork'は画像を処理するもので、' calculatorComplete'は処理された画像を送ります。必要なスレッド数は見積もるのが難しいです。イメージ処理のためのメインスレッドとスレッドから始めます。パフォーマンスを測定します。悪い場合は、スレッドを追加してみてください。また、さまざまな[マルチスレッド技術](http://doc.qt.io/qt-5/threads-technologies.html)もチェックしてください。Qtが提供しなければなりません。 – thuga

関連する問題