3

私は C++/Qt のスレッドで作業しており、それぞれが QTcpSocket 接続を確立して維持しています。

問題は、ネットワークから切断されたときに、それらのスレッドが特定の順序で再接続する必要があることです。それはすでに機能していますが、別の問題があります。現在のスレッドのみが切断されているか、すべてが切断されているかを各スレッドで知る必要があります。

私が思いついた最初のアイデアは、各スレッドのステータスを保存し、他のすべてのスレッドのステータスをチェックできるクラスへの参照をすべてのスレッドに渡すことでした。

しかし、私はより簡単なアイデアを思いついたので、それが機能するかどうか、または不可能かどうかを知りたいと思います: Qt のスロットとシグナルを使用します。

したがって、私が持っているすべてのスレッドは同じクラスから来ていますが、異なるデータを Ctor に渡しています。そのため、そのクラス内にスロットとシグナルを作成し、それらを接続して、ID を渡すシグナルを発信するという考えになります。次に、すべてのスレッドのスロットが起動されます...または私が完全に間違っている可能性があり、起動された唯一のスロットは、信号を発信したまったく同じスレッドからのスロットになります。

これは可能ですか?

4

2 に答える 2

4

まず、シグナルとスロットの接続は、スレッド間ではなく、QObjects のシグナルとスロット間で行われます。QThread は QObject ですが、QThread から派生させるべきではありません。QThread から派生させないでください。問題ありません。

あなたがすることは次のとおりです。

  1. 1 つ以上の QThreadsを開始します(単に構築するだけではありません)。これらの QThreads は単なる Qt の基本クラスであり、それらから派生するものではありません。開始された raw QThread はブロックされ、イベントがそのイベント キューにポストされるのを待ちます。QThread::run()呼び出しのデフォルトの実装QEventLoop::exec()(または同等のもの)。したがって、これらのスレッドは、開始後、CPU サイクルを消費しません。

  2. 一連の QObject をインスタンス化します。必要に応じて、すべての信号/スロット接続を行います。

  3. それらを呼び出して、これらのオブジェクトを 1 つ以上の QThreads に移動moveToThread(QThread*)します。

ご覧のとおり、信号スロット接続の設定は通常の方法で行われ、特別な注意は必要ありません。Qt::DirectConnectionQt は、スレッド間で QObject を移動するQt::QueuedConnectionときに接続タイプを から に変更するなど、すべてを行います。

これらの QObject のメソッドを直接呼び出してはならないことに注意してください。別のスレッドから呼び出す可能性が高いため、アクセスがシリアル化されていないため、あらゆる種類の悪いことが起こります。以下のいずれかを実行する必要がありますが、これだけを、最速から低速の順に実行する必要があります。#3 は常に #4 より高速ですが、変化するので #2 と #3 の間でベンチマークを行う必要があることに注意してください。

  1. カスタム イベントを QObject に投稿し、派生した QObject のcustomEvent(QEvent*)メソッドで処理します。

  2. シグナルスロット接続を使用し、QObjects のスロットに接続されたシグナルを送信します。

  3. QMetaMethod::invoke以前に検索したメソッドで使用します。メソッド ルックアップが事前に 1 回だけ行われるため、#4 よりも高速です。

  4. を使用しQMetaObject::invokeMethodます。

QEvents を QObjects にポストすることは、シグナルスロット呼び出しを使用するよりも高速です。これは、呼び出されるコピー コンストラクターがなく、QEvent の構築時にユーザーが直接行う場合を除き、マーシャリングが行われないためです。

プロファイリング/ベンチマークにより、イベントの投稿が遅すぎることが示されている場合にのみ、 の使用を検討してQSharedMemoryください。QThreads の数が多すぎると逆効果です。おそらく、システムの CPU コアの数を超えないようにする必要があります。単純にミューテックスやセマフォなどの同期プリミティブを使用すると、あまりにも多くのスレッドをコミットする必要があります。接続ごとに 1 つのスレッドを使用する必要はありません。Qt には、すでに使用しているイベント キューを使用して、各 QObject のイベント キュー ミューテックスが既にあります。

于 2012-05-31T19:10:31.170 に答える
2

シグナルとスロットの接続は実行時に行われます。つまり、クラスの特定のインスタンスを接続しています。シグナルを発行して、クラスのすべてのインスタンスに「ブロードキャスト」することはできません。異なるスレッド間のシグナルは可能ですが、それらを維持するのは少し面倒かもしれません (ドキュメントですべて説明されています)。

私があなただったら、おそらくQSemaphoreまたはQSharedMemoryを調べるでしょう。

于 2012-05-31T11:37:14.330 に答える