コンカレント・ラン
QtConcurrent::run() 関数は、別のスレッドで関数を実行します。関数の戻り値は、QFuture API を通して利用可能です。
QtConcurrent::run() はオーバーロードされたメソッドです。これらのオーバーロードは、わずかに異なるモードと考えることができます。基本モードでは、QtConcurrent::run() に渡された関数は、呼び出し元に単一の計算結果のみを報告します。プロミス付き実行モードでは、QtConcurrent::run() に渡された関数は、追加のQPromise API を使用することができます。この API を使用することで、複数の結果報告、進捗報告、呼び出し元の要求による計算の一時停止、呼び出し元の要求による計算の停止が可能になります。
この関数は、Qt Concurrent フレームワークの一部です。
同時実行(基本モード)
QtConcurrent::run() に渡された関数は、その戻り値を通して結果を報告することができます。
別スレッドでの関数の実行
別のスレッドで関数を実行するには、QtConcurrent::run() を使用します:
extern void aFunction(); QFuture<void> future = QtConcurrent::run(aFunction);
これは、デフォルトのQThreadPool から取得した別のスレッドでaFunction
を実行します。QFuture とQFutureWatcher クラスを使用して、関数の状態を監視することができます。
専用のスレッド・プールを使用するには、最初の引数にQThreadPool を渡します:
extern void aFunction(); QThreadPool pool; QFuture<void> future = QtConcurrent::run(&pool, aFunction);
関数に引数を渡す
関数に引数を渡すには、QtConcurrent::run() 呼び出しの関数名の直後に引数を追加します。例えば
extern void aFunctionWithArguments(int arg1, double arg2, const QString &string); int integer = ...; double floatingPoint = ...; QString string = ...; QFuture<void> future = QtConcurrent::run(aFunctionWithArguments, integer, floatingPoint, string);
各引数のコピーは、QtConcurrent::run() が呼び出された時点で作成され、これらの値は、関数の実行を開始するときにスレッドに渡されます。QtConcurrent::run() を呼び出した後に引数に加えられた変更は、スレッドからは見えません。
QtConcurrent::run は、オーバーロードされた関数を直接呼び出すことをサポートしていないことに注意してください。例えば、以下のコードはコンパイルできません:
void foo(int arg); void foo(int arg1, int arg2); ... QFuture<void> future = QtConcurrent::run(foo, 42);
最も簡単な回避策は、ラムダを通してオーバーロード関数を呼び出すことです:
QFuture<void> future = QtConcurrent::run([] { foo(42); });
あるいは、static_cast
:
QFuture<void> future = QtConcurrent::run(static_cast<void(*)(int)>(foo), 42);
またはqOverload :
QFuture<void> future = QtConcurrent::run(qOverload<int>(foo), 42);
関数から値を返す
関数からの戻り値は、QFuture :
extern QString functionReturningAString(); QFuture<QString> future = QtConcurrent::run(functionReturningAString); ... QString result = future.result();
結果が不要な場合(例えば、関数がvoid
を返す場合など)は、QThreadPool::start() オーバーロードを使用して関数オブジェクトを取得する方が効率的です。
上で説明したように、引数の受け渡しは次のように行います:
extern QString someFunction(const QByteArray &input); QByteArray bytearray = ...; QFuture<QString> future = QtConcurrent::run(someFunction, bytearray); ... QString result = future.result();
QFuture::result() 関数は、ブロックして結果が利用可能になるのを待つことに注意してください。関数の実行が終了し、結果が利用可能になったときに通知を受け取るには、QFutureWatcher を使用してください。
その他のAPI機能
メンバ関数の使用
QtConcurrent::run() は、メンバ関数へのポインタも受け付けます。最初の引数は、const 参照またはクラスのインスタンスへのポインタのいずれかでなければなりません。const参照で渡すと、constメンバ関数を呼び出すときに便利です。ポインタで渡すと、インスタンスを変更する非constメンバ関数を呼び出すときに便利です。
例えば、QByteArray::split() (constメンバ関数)を別のスレッドで呼び出すと、次のようになる:
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread QByteArray bytearray = "hello world"; QFuture<QList<QByteArray> > future = QtConcurrent::run(&QByteArray::split, bytearray, ' '); ... QList<QByteArray> result = future.result();
constでないメンバ関数を呼び出す場合は、次のようになります:
// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread QImage image = ...; QFuture<void> future = QtConcurrent::run(&QImage::invertPixels, &image, QImage::InvertRgba); ... future.waitForFinished(); // At this point, the pixels in 'image' have been inverted
ラムダ関数の使用
ラムダ関数の呼び出しは次のように行う:
QFuture<void> future = QtConcurrent::run([=]() { // Code in this block will run in another thread }); ...
参照渡しされたオブジェクトを変更する関数の呼び出しは次のように行う:
static void addOne(int &n) { ++n; } ... int n = 42; QtConcurrent::run(&addOne, std::ref(n)).waitForFinished(); // n == 43
呼び出し可能なオブジェクトを使用する場合は次のようになる:
struct TestClass { void operator()(int s1) { s = s1; } int s = 42; }; ... TestClass o; // Modify original object QtConcurrent::run(std::ref(o), 15).waitForFinished(); // o.s == 15 // Modify a copy of the original object QtConcurrent::run(o, 42).waitForFinished(); // o.s == 15 // Use a temporary object QtConcurrent::run(TestClass(), 42).waitForFinished(); // Ill-formed QtConcurrent::run(&o, 42).waitForFinished(); // compilation error
プロミスによる同時実行
プロミス付き実行モードでは、QtConcurrent::run() の基本モードと比較して、実行中のタスクの制御がより容易になります。実行中のタスクの進捗報告、複数の結果の報告、要求があった場合の実行の一時停止、呼び出し元の要求によるタスクのキャンセルなどが可能です。
必須のQPromise引数
QPromise<T> &
ここでT
は計算結果の型です(QtConcurrent::run() が返すQFuture<T> の型T
と一致する必要があります):
extern void aFunction(QPromise<void> &promise); QFuture<void> future = QtConcurrent::run(aFunction);
引数promise
は、QtConcurrent::run() 関数内でインスタンス化され、その参照は呼び出されたaFunction
に渡されるため、このモードで QtConcurrent::run() を呼び出す場合、ユーザはインスタンス化したり、明示的に渡す必要はありません。
このモードで QtConcurrent::run() を呼び出す場合、ユーザはインスタンス化する必要も、明示的に渡す必要もありません。QPromise 型の追加引数は、関数の引数リストの第 1 引数として表示される必要があります:
extern void aFunction(QPromise<void> &promise, int arg1, const QString &arg2); int integer = ...; QString string = ...; QFuture<void> future = QtConcurrent::run(aFunction, integer, string);
結果の報告
QtConcurrent::run() の基本モードとは対照的に、Run With Promiseモードで QtConcurrent::run() に渡される関数は、常に void 型を返すことが期待されています。結果報告は、QPromise 型の追加引数を通して行われます。のように、複数の結果報告も可能です:
void helloWorldFunction(QPromise<QString> &promise) { promise.addResult("Hello"); promise.addResult("world"); } QFuture<QString> future = QtConcurrent::run(helloWorldFunction); ... QList<QString> results = future.results();
注意: 計算の開始と終了を示すためにQPromise::start() とQPromise::finish() を呼び出す必要はありません(通常QPromise を使用する場合のように)。QtConcurrent::run()は、実行の開始前と終了後に必ず呼び出します。
実行の中断とキャンセル
QPromise API は、要求があれば、計算の中断とキャンセルも可能です:
void aFunction(QPromise<int> &promise) { for (int i = 0; i < 100; ++i) { promise.suspendIfRequested(); if (promise.isCanceled()) return; // computes the next result, may be time consuming like 1 second const int res = ... ; promise.addResult(res); } } QFuture<int> future = QtConcurrent::run(aFunction); ... // user pressed a pause button after 10 seconds future.suspend(); ... // user pressed a resume button after 10 seconds future.resume(); ... // user pressed a cancel button after 10 seconds future.cancel();
future.suspend()
を呼び出すと、実行中のタスクに実行の保留を要求する。このメソッドを呼び出すと、実行中のタスクは反復ループ内でpromise.suspendIfRequested()
を次に呼び出した後に中断する。この場合、実行中のタスクはpromise.suspendIfRequested()
への呼び出しでブロックされる。ブロックされた呼び出しは、future.resume()
が呼び出された後にブロックが解除される。内部的には、suspendIfRequested()はブロックを解除するためにwait条件を使用するので、実行中のスレッドは、再開要求が呼び出し元のスレッドから来たかどうかを定期的にチェックするために、ブロックされたときにリソースを浪費する代わりにアイドル状態になる。
最後の行のfuture.cancel()
への呼び出しにより、promise.isCanceled()
への次の呼び出しはtrue
を返し、aFunction
はそれ以上結果を報告することなく即座に戻る。
注意: キャンセル後に計算を停止するためにQPromise::finish() を呼び出す必要はありません(通常QPromise を使用する場合のように)。QtConcurrent::run()は、常に実行終了後に呼び出されます。
進捗報告
結果報告とは別に、タスクの進捗を報告することも可能です:
voidaFunction(QPromise<int> &promise) { promise.setProgressRange(0, 100);intresult= 0;for(inti= 0; i< 100;++i) {// タスクの一部を計算する const intpart= ...; result+=part; promise.setProgressValue(i); } promise.addResult(result); } のようなことも可能です。QFutureWatcher<int>watcher;QObject::connect(&watcher, &)QFutureWatcher::progressValueChanged, [](intprogress){ ...;// GUIを進捗で更新する。 qDebug() << "current progress:" << progress; }); watcher.setFuture(QtConcurrent::run(aFunction));
呼び出し元は、QtConcurrent::run() によって返されたQFuture
のQFutureWatcher
をインストールし、そのprogressValueChanged()
シグナルに接続し、それに応じてグラフィカルユーザインターフェイスなどを更新します。
オーバーロードされた operator()() による関数の呼び出し
デフォルトでは、QtConcurrent::run() は、Run With Promiseモードでオーバーロードされた operator()() を持つファンクタをサポートしていません。オーバーロードされたファンクタの場合、QtConcurrent::run() に渡されるテンプレートパラメータとして、結果の型を明示的に指定する必要があります:
© 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.