Qt シグナルに問題があります。
DirectConnection
私はどのように動作するのか理解していませんQueuedConnection
か?
これらのどれをいつ使用するかを誰かが説明してくれるとありがたいです (サンプル コードをいただければ幸いです)。
Qt シグナルに問題があります。
DirectConnection
私はどのように動作するのか理解していませんQueuedConnection
か?
これらのどれをいつ使用するかを誰かが説明してくれるとありがたいです (サンプル コードをいただければ幸いです)。
異なるスレッド アフィニティを持つオブジェクトを操作しない限り、大きな違いは見られません。A
QObjects がありB
、それらが両方とも異なるスレッドに接続されている としましょう。A
には という信号がsomethingChanged()
ありB
、 というスロットがありhandleChange()
ます。
直結でご利用の場合
connect( A, SIGNAL(somethingChanged()), B, SLOT(handleChange()), Qt::DirectConnection );
メソッドhandleChange()
は実際にはA
のスレッドで実行されます。基本的には、シグナルを発行してスロット メソッドを「直接」呼び出しているかのようです。スレッドセーフでない場合B::handleChange()
、(見つけにくい) バグが発生する可能性があります。少なくとも、余分なスレッドの利点を逃しています。
接続方法を に変更するとQt::QueuedConnection
(または、この場合、使用する方法を Qt に決定させる)、事態はさらに興味深いものになります。のスレッドがイベント ループを実行していると仮定するとB
、シグナルを発行すると、イベントがB
のイベント ループに送信されます。イベント ループはイベントをキューに入れ、最終的に制御が戻るたびにスロット メソッドを呼び出します (イベント ループです)。これにより、Qt のスレッド間/スレッド間での通信を非常に簡単に処理できます (ここでも、スレッドが独自のローカル イベント ループを実行していると仮定します)。イベント ループがスロット呼び出しをシリアル化するため、ロックなどについて心配する必要はありません。
注: QObject のスレッド アフィニティを変更する方法がわからない場合は、 を参照してQObject::moveToThread
ください。これで始められるはずです。
編集
冒頭の文を明確にする必要があります。同じスレッド上の2つのオブジェクトであっても、キュー接続を指定すると違いが生じます。イベントは引き続きスレッドのイベント ループにポストされます。したがって、メソッド呼び出しはまだ非同期です。つまり、予測できない方法で遅延する可能性があります (ループが処理する必要がある他のイベントによって異なります)。ただし、接続メソッドを指定しない場合、同じスレッド上のオブジェクト間の接続にはダイレクト メソッドが自動的に使用されます (少なくとも Qt 4.8 ではそうです)。
Jacob Robbinsの回答に加えて:
「異なるスレッド アフィニティを持つオブジェクトを操作しない限り、大きな違いは見られない」というステートメントは間違っています。
同じスレッド内の直接接続にシグナルを送信すると、単純な関数呼び出しと同じように、スロットがすぐに実行されます。
同じスレッド内のキューに入れられた接続にシグナルを送信すると、呼び出しがスレッド イベント ループのキューに入れられるため、実行は常に遅れて発生します。
ジェイコブの答えは素晴らしいです。組み込みプログラミングとの比較例を追加したいと思います。
組み込み RTOS/ISR のバックグラウンドから来て、ISR のプリエンプティブ動作への Qt の DirectConnection とタスク間の RTOS での Qt の QueuedConnection への QueuedConnection の類似性を確認することは役に立ちました。
補足: 組み込みのバックグラウンドを持っているため、プログラミングで動作を定義しないことは困難です。私は議論をAutoとして放置することは決してありませんが、それは単なる個人的な意見です. 私はすべてが明示的に書かれていることを好みます。