6

ワーカー オブジェクトを実行するスレッドを作成しました。すべて正常に動作します。また、結果の信号は、必要に応じて送信されます。もちろん、スレッドとオブジェクトのアフィニティに関するよくある間違いには対処しました。

今日、私はこれらのワーカー/スレッドの自動モジュール テストを作成しました。次のように、(スレッドに移動された) ワーカー オブジェクトによって発行されるシグナルを待機する QSignalSpy を作成しました。

QSignalSpy spy(worker, SIGNAL(Success()));
thread.ExecuteWorker();
QVERIFY(spy.wait()); // Error in this line

マークされた行でよく知られているエラーが発生しています。

QObject::killTimer: timers cannot be stopped from another thread

最初に、wait() の一部のコードが間違ったスレッドで実行されたため、エラーが発生することが予想されました。次に、QSignalSpy の実装で次のコードを見つけました。

if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0))
{
   qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
   return;
}

これは明らかに、QSignalSpy が常に DirectConnection を使用し、異なるスレッドに存在するオブジェクトのシグナルを監視するために使用できないことを意味します。

なぜQt5.3でそのようにプログラムしたのですか? それは間違いですか、それとも意図した動作ですか? この制限を回避するにはどうすればよいですか?

4

2 に答える 2

6

残念ながら、これは長期にわたる問題であり、公正であるためには 6 年以上かかります。

シグナルがワーカー スレッドから送信されると QSignalSpy がクラッシュする

私は数年前の Qt Contributor Summit で Jason に会いましたが、彼が働いていたブリスベン オフィスを Nokia が閉鎖したため、その後すぐに Nokia を離れました。その後、残念ながらこの Qt のテスト モジュールではあまり貢献がありませんでした。

最近、メーリングリストでもそれについての議論がありました:

QSignalSpy が Qt::DirectConnection を使用するのはなぜですか?

Roland によって提案された解決策は、メンテナーである Thiago も受け入れた次のとおりです。

if (thread() != QThread::currentThread())
{
    QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection);
    return;
}

これが 5.4 より前に導入されなかったのは本当に残念です。そうは言っても、変更がマージされたため、これは Qt 5.4 で修正されます。

QTestEventLoop::exitLoop() をスレッドセーフにする

于 2014-12-06T21:06:36.423 に答える