0

から派生したクラスがありQThreadます: class MyClass : public QThread このクラスは別のオブジェクトのスロットに接続されています。もともとこれは として接続されていましQt::AutoConnectionた。しかし、スレッドが開始されるとすぐに ( MyClass::run())、シグナルが「スロットに到達」しなくなります (なぜですか? )。

// connected before myObject->run()
s = QObject::connect(
_myObject, SIGNAL(signalLogMessage(const QString&, QtMsgType)), 
this, SLOT(slotLogMessage(const QString&, QtMsgType)), Qt::DirectConnection);

私の最初のアイデアは、強制する必要があるということでしたQt::QueuedConnectionthis/_myObjectはクロススレッドになります)。この場合、まったく機能しません。のみQt::DirectConnection動作します。スレッドが開始された後は、IMHOQt::QueuedConnectionが正しい選択です (クロス スレッド)。

何がうまくいかないのですか?接続自体は正しいようQt::DirectConnectionです。

編集1: - ハイドの答え/ニコスのコメントの時点で

現時点では、ハイドの答え/ニコスのコメントが根本的な原因を指摘していると思います。私QThreadは別のアプリケーションに対して独自のメッセージループを実行しています。これが独自のスレッドで実行され、基本的に無限ループである理由です。

run() { 
  // exec(); // while not reached    
  while (_runMessageLoop && ...) {
    hr = CallDispatch(.....);
    if (hr== 0) QThread::msleep(100); 
    // QCoreApplication::processEvents();
  }
}

この無限ループが原因で、Qt メッセージ ループが実行されておらず、シグナル/スロットが処理されていないと推測します (これは正しいですか?) Qt::DirectConnectionQt メッセージ ループを必要とせずに直接メソッドを強制的に呼び出す場合、これが唯一の接続タイプの作業。

問題は、Qt と自分のメッセージ ループをどのように組み合わせることができるかということです(これが実現可能な場合)。ループの前に exec() を呼び出すことはできません (Qt ループ内にあるため) QCoreApplication::processEvents();

=> ここで新しい質問を参照してください:独自のメッセージ ループと Qt イベント ループを組み合わせる方法は?

4

1 に答える 1

2

すべてのコードを見ないとなんとも言えませんが、次の理由が考えられます。

QThread オブジェクト自体はスレッドではなく、スレッド コントローラーです。最も重要なこととして、QThread オブジェクトのスレッド アフィニティは、それが制御するスレッドであってはなりません。スレッドが Qt イベント ループを実行する場合は、QThread のサブクラス化を避けるのが最善です。代わりに、作成後に moveToThread で作成したスレッドに移動する別の QObject にロジック (スレッド間スロットなど) を配置します。QThread をサブクラス化する唯一の本当の理由は、run()メソッドを呼び出さないメソッドでオーバーライドすることexec()です。

関連資料: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong

追加: QThread::run() をオーバーライドする場合は、QThread::exec()そこを呼び出す必要があります。そうしないと、イベント ループが実行されず、非直接シグナルがそのスレッド アフィニティを持つ QObject に配信されません。独自のイベント ループが必要な場合は、それが可能ですQCoreApplication::processEvents()。Qt イベントを処理するために呼び出すだけです。

于 2012-10-20T18:55:47.710 に答える