moveToThread
は、サブクラス化QThread
よりも優先する必要があるのはいつですか?
このリンク は、両方の方法が機能することを示しています。これらの2つから何を使用するかをどの基準で決定する必要がありますか?
2つの方法の違いに焦点を当てます。すべてのユースケースに当てはまる一般的な答えはありません。そのため、それらが何であるかを正確に理解して、あなたのケースに最適なものを選ぶのは良いことです。
moveToThread()は、オブジェクトのスレッドアフィニティを制御するために使用されます。これは、基本的にスレッドの設定(またはより良いQtイベントループ)。オブジェクトはそこからシグナルを発行し、そのスロットが実行されます。
リンクしたドキュメントに示されているように、これは別のスレッドでコードを実行するために使用でき、基本的にダミーワーカーを作成し、実行するコードを記述しますapublic slot(この例ではdoWork()スロット)を使用し、次にmoveToThreadを別のイベントループに移動します。
次に、そのスロットに接続されている信号が発生します。シグナルを送信するオブジェクト(例ではController)は別のスレッドにあり、シグナルはキュー接続でdoWorkメソッドに接続されているため、doWorkメソッドはワーカースレッドで実行されます。
ここで重要なのは、ワーカースレッドによって実行される新しいイベントループを作成していることです。したがって、doWorkスロットが開始されると、イベントループ全体が終了するまでビジー状態になり、これは着信信号がキューに入れられることを意味します。
Qtのドキュメントで説明されているもう1つの方法は、QThreadのサブクラス化です。この場合、QThread :: run()メソッドのデフォルト実装をオーバーライドして、イベントループを作成し、別の何かを実行します。
いくつかの落とし穴がありますが、このアプローチ自体に問題はありません。
まず、run()メソッドはそのクラスで実際に別のスレッドで実行される唯一のメソッドであるため、安全でないコードを書くのは非常に簡単です。
例として、コンストラクターで初期化し、run()メソッドで使用するメンバー変数がある場合、メンバーは呼び出し元のスレッドで初期化され、次に新しいスレッドで使用されます。
呼び出し元から、またはrun()内から呼び出すことができる任意のパブリックメソッドについても同じことが言えます。
また、スロットは呼び出し側のスレッドから実行されます(moveToThread(this)として本当に奇妙なことをしない限り)、さらに混乱が生じます。
だから、それは可能ですが、あなたは本当にあなた自身がこのアプローチであなた自身にあり、あなたは特別な注意を払う必要があります。
もちろん、必要に応じて、両方のアプローチに代わるものがあります。 GUIスレッドの実行中にコードをバックグラウンドで実行するだけの場合は、 QtConcurrent :: run() の使用を検討してください。
ただし、QtConcurrentはグローバルQThreadPoolを使用することに注意してください。プール全体がビジーの場合(つまり、プールに使用可能なスレッドがない場合)、コードはすぐには実行されません。
別の方法として、少なくともC++ 11を使用している場合は、 std :: thread などの低レベルのAPIを使用します。
開始点として、どちらも使用しないでください。ほとんどの場合、非同期で実行したい作業単位があります。使用する - QtConcurrent::run
そのため。
イベントに反応したりタイマーを使用したりするオブジェクトがある場合、それはQObject
であり、非ブロッキングでスレッドに移動する必要があります。おそらく他のオブジェクトと共有されます。
このようなオブジェクトは、ブロッキングAPIをラップすることもできます。
QThread
のサブクラス化は、実際には必要ありません。 QFile
をサブクラス化するようなものです。 QThread
はスレッドハンドルです。システムリソースをラップします。オーバーロードは少しばかげています。
QThreadは低レベルのスレッド抽象化です。最初に高レベルのAPIを見てください QtConcurrent モジュールと QRunnable
これらのどれもあなたに適していない場合は、 この古い記事 を読んで、QThreadの使用方法を説明します。このスレッドで実行されるスレッドとタスクを個別のオブジェクトとして考え、それらを一緒に混ぜないでください。
したがって、カスタム、特定、または拡張スレッドラッパーを記述する必要がある場合は、QThreadをサブクラス化する必要があります。
シグナルとスロットを持つQObject派生クラスがある場合は、そのクラスでmoveToThreadを使用します。
他の場合では、QtConcurrent、QRunnable、QThreadPollを使用します。
単純な答えは常にです。オブジェクトをスレッドに移動すると:
QThread
をサブクラス化するとき
Qtブログからの問題の完全な説明があります: あなたはそれを間違っています... 。
QtConcurrent::run
も非常に便利です。
デフォルトでは、他のスレッドオブジェクトが割り当てられているスレッドから信号が送信されると、スロットは踏み板の間をジャンプしようとします。詳細は Qt :: ConnectionType のドキュメントを参照してください。