web-dev-qa-db-ja.com

QtはQueuedConnectionを使用して2つの信号を接続します

Qt documentation は、2つの信号を一緒に接続することが可能であることを示しています。

信号を別の信号に直接接続することも可能です。

私は試した:

connect(x, SIGNAL(S()), y, SIGNAL(func()));

そしてそれは前述のように動作しますが、Qtのドキュメントは続きます:

(これにより、最初の信号が発信されるとすぐに2番目の信号が発信されます。

これは、QueuedConnectionが正しく機能しないことを意味しますか?スレッド間で2つの信号を接続できますか?

私がこれを尋ねる理由は、これを回避することでアプリケーションのクラスのクラッシュを解決したためですが、これが信号の接続に関連していたかどうかはわかりません。

25
dashesy

信号/スロット接続と大きく異なることはありません。信号/スロットの基本的なメカニズムを見てみましょう。各スレッドには、発行されたがまだ処理されていないシグナル(イベント)を保持するイベントキューがあります。したがって、実行がイベントループに戻るたびに、キューが処理されます。イベントループ自体はイベントを処理しません。むしろ、それらをオブジェクトに配信して処理できるようにします。この特殊なケースでは、オブジェクトがキューに挿入される別のシグナルを送信するとします。実行がイベントループに戻ると、新しい信号はオブジェクトによって再び処理されます。これは、上記の議論を証明するテストです。

添付されたコードを実行すると、出力は次のようになります。

before signal() 
after signal() 
slot() called

これは、スレッド間でキューに入れられるときにシグナル-シグナル接続タイプを定義すると、予期されるキューに入れられた動作があり、常に即時である引数を拒否することを意味します。これを直接として定義すると、出力は次のようになります。

before signal()
slot() called 
after signal()

予想通り。エラーや警告は発生せず、プログラムもクラッシュしませんが、この単純な例では、大規模で複雑な例でも機能することを証明していません。

main.cpp:

#include <QtGui/QApplication>
#include "dialog.h"
#include "testssconnection.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TestSignalSignalConnection * t = new TestSignalSignalConnection();
    t->start();

    return a.exec();
}

testssconnection.h:

#ifndef TESTSSCONNECTION_H
#define TESTSSCONNECTION_H

#include <QObject>
#include <QThread>

class TestSignalSignalConnection : public QThread
{
    Q_OBJECT
public:
    explicit TestSignalSignalConnection(QObject *parent = 0);

    void run();

signals:
    void signal1();
    void signal2();

public slots:
    void slot();
};

#endif // TESTSSCONNECTION_H

testssconnection.cpp:

#include "testssconnection.h"
#include <QtCore>

TestSignalSignalConnection::TestSignalSignalConnection(QObject *parent) :
    QThread(parent)
{
}

void TestSignalSignalConnection::run()
{
    TestSignalSignalConnection *t = new TestSignalSignalConnection();

    this->connect(this,SIGNAL(signal1()),t,SIGNAL(signal2()), Qt::QueuedConnection);
    t->connect(t,SIGNAL(signal2()), t,SLOT(slot()), Qt::DirectConnection);

    qDebug() << "before signal()";
    emit signal1();
    qDebug() << "after signal()";

    exec();
}

void TestSignalSignalConnection::slot()
{
    qDebug() << "slot() called";
}
29
Ameer Jewdaki

スレッドとシグナルに関するすばらしいwikiページであるqt-projectをご覧ください。

スレッド、イベント、QObjects :: Signalsとスレッド間のスロット

1
kikeenrique