Qt におけるマルチスレッド技術
Qt にはスレッドを扱うためのクラスや関数がたくさんあります。以下は、Qt プログラマがマルチスレッドアプリケーションを実装するために使用できる 4 つの異なるアプローチです。
QThread:オプションのイベントループを持つ低レベル API
QThread は Qt におけるすべてのスレッド制御の基礎です。各 インスタンスは、1 つのスレッドを表し、制御します。QThread
QThread QThread は直接インスタンス化することも、サブクラス化することもできます。 をインスタンス化すると、並列イベントループが提供され、 スロットをセカンダリスレッドで呼び出すことができます。 をサブクラス化すると、アプリケーションはイベント・ループを開始する前に新しいスレッドを初期化したり、イベント・ループなしで並列コードを実行できるようになります。QThread QObject QThread
QThread の使用方法については、QThread class reference とスレッド作成例を参照してください。
QThreadPool と QRunnable:スレッドの再利用
スレッドを頻繁に作成したり破棄したりするには、コストがかかります。このオーバーヘッドを減らすために、既存のスレッドを新しいタスクに再利用することができます。QThreadPool は、再利用可能な QThreads のコレクションです。
QThreadPool のスレッドの 1 つでコードを実行するには、QRunnable::run() を再実装し、サブクラス化されたQRunnable をインスタンス化します。QRunnable をQThreadPool の実行キューに入れるには、QThreadPool::start() を使用します。スレッドが使用可能になると、QRunnable::run() 内のコードがそのスレッドで実行されます。
各 Qt アプリケーションにはグローバル・スレッド・プールがあり、QThreadPool::globalInstance() からアクセスできます。このグローバル・スレッド・プールは、CPUのコア数に基づいて最適なスレッド数を自動的に維持します。しかし、QThreadPool を個別に作成し、明示的に管理することもできます。
Qt Concurrent:高レベルAPIの使用
この Qt Concurrentモジュールは、一般的な並列計算パターンである map、filter、reduce を扱う高レベル関数を提供します。QThread やQRunnable を使用するのとは異なり、これらの関数はミューテックスやセマフォのような低レベルのスレッドプリミティブを使用する必要はありません。代わりに、QFuture オブジェクトを返します。このオブジェクトは、準備ができたときに関数の結果を取得するために使用できます。QFuture は、計算の進行状況を照会したり、計算を一時停止/再開/キャンセルしたりするためにも使用できます。便宜上、QFutureWatcher はシグナルとスロットを介してQFutureと相互作用することができる。
Qt Concurrentマップ、フィルター、リデュースの各アルゴリズムは、利用可能なすべてのプロセッサー・コアに計算を自動的に分散させるので、今日書かれたアプリケーションは、後でコア数の多いシステムにデプロイされたときにも拡張し続けることができる。
このモジュールはQtConcurrent::run() 関数も提供しており、別のスレッドで任意の関数を実行できる。しかし、QtConcurrent::run ()は、map、filter、reduce関数で利用可能な機能のサブセットしかサポートしていない。QFuture は、関数の戻り値を取得したり、スレッドが実行中かどうかをチェックするために使用できます。ただし、QtConcurrent::run() の呼び出しは、1 つのスレッドのみを使用し、一時停止/再開/キャンセルはできず、進行状況を問い合わせることもできません。
各関数の詳細については Qt Concurrentモジュールのドキュメントを参照してください。
WorkerScript を参照してください:QML でのスレッド処理
WorkerScript QMLタイプはJavaScriptコードをGUIスレッドと並行して実行させます。
各WorkerScript インスタンスには.js
スクリプトを1つアタッチすることができます。WorkerScript.sendMessage() が呼び出されると、スクリプトは別のスレッドで実行されます (QML context も別です)。スクリプトの実行が終了すると、WorkerScript.onMessage() シグナル・ハンドラを呼び出すGUIスレッドに応答を送り返すことができます。
WorkerScript を使用するのは、別のスレッドに移動したワーカーQObject を使用するのと似ている。データはシグナルを介してスレッド間で転送されます。
スクリプトの実装方法の詳細や、スレッド間で受け渡し可能なデータ型のリストについては、WorkerScript のドキュメントを参照してください。
適切なアプローチの選択
上記で示したように、Qt はスレッドアプリケーションを開発するためのさまざまなソリューションを提供します。あるアプリケーションに適したソリューションは、新しいスレッドの目的とスレッドの寿命に依存します。以下に、Qt のスレッド技術の比較と、いくつかの使用例に対する推奨ソリューションを示します。
ソリューションの比較
機能 | QThread | QRunnable そしてQThreadPool | QtConcurrent::run() | Qt Concurrent (マップ、フィルタ、リデュース) | WorkerScript |
---|---|---|---|---|---|
言語 | C++ | C++ | C++ | C++ | QML |
スレッド優先度指定可能 | あり | あり | |||
スレッドはイベントループを実行できる | 可 | ||||
スレッドはシグナルを通してデータ更新を受け取ることができる | はい (ワーカーによって受信QObject) | はい (WorkerScript で受信) | |||
スレッドはシグナルを使って制御できる | はい(QThread によって受信) | はい(QFutureWatcher によって受信) | |||
スレッドはQFuture | 部分的に | あり | |||
一時停止/再開/キャンセル機能内蔵 | あり |
使用例
スレッドの寿命 | 操作 | 解決方法 |
---|---|---|
1回の呼び出し | 別のスレッド内で新しい一次関数を実行します。 | Qt はさまざまなソリューションを提供しています:
|
コール | 別のスレッド内で既存の関数を実行し、その戻り値を取得する。 | QtConcurrent::run() を使って関数を実行する。関数が返ったらQFutureWatcher にfinished() シグナルを出させ、QFutureWatcher::result() を呼び出して関数の戻り値を取得する。 |
1回の呼び出し | 利用可能なすべてのコアを使用して、コンテナのすべてのアイテムに対して操作を実行する。たとえば、画像のリストからサムネイルを生成する。 | Qt Concurrent のQtConcurrent::filter() 関数を使用してコンテナ要素を選択し、QtConcurrent::map() 関数を使用して各要素に処理を適用する。出力を単一の結果に折りたたむには、代わりにQtConcurrent::filteredReduced() とQtConcurrent::mappedReduced() を使用します。 |
ワンコール/パーマネント | 純粋なQMLアプリケーションの中で長い計算を行い、結果の準備ができたらGUIを更新します。 | 計算コードを.js スクリプトに記述し、WorkerScript インスタンスにアタッチします。WorkerScript.sendMessage() を呼び出し、新しいスレッドで計算を開始します。スクリプトもsendMessage()を呼び出して、結果をGUIスレッドに戻します。結果をonMessage で処理し、そこでGUIを更新する。 |
パーマネント | 別のスレッドに、要求に応じて別のタスクを実行したり、新しいデータを受け取ったりできるオブジェクトを常駐させます。 | QObject をサブクラス化してワーカーを作成します。このワーカーオブジェクトとQThread をインスタンス化します。 ワーカーを新しいスレッドに移動します。キューイングされたシグナルスロット接続を介して、ワーカーオブジェクトにコマンドやデータを送る。 |
パーマネント | スレッドがシグナルやイベントを受け取る必要のない別のスレッドで、高価な処理を繰り返し実行する。 | QThread::run() の再実装の中に直接無限ループを書く。イベント・ループなしでスレッドを開始する。スレッドにシグナルを発行させ、GUIスレッドにデータを送り返す。 |
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.