QFuture Class

template <typename T> class QFuture

QFuture クラスは、非同期計算の結果を表します。詳細...

Header: #include <QFuture>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

注:このクラスの関数は、以下の例外を除いてすべてスレッドセーフです:

パブリック・タイプ

パブリック関数

QFuture()
QFuture(const QFuture<T> &other)
~QFuture()
QFuture<T>::const_iterator begin() const
void cancel()
QFuture<T>::const_iterator constBegin() const
QFuture<T>::const_iterator constEnd() const
QFuture<T>::const_iterator end() const
bool isCanceled() const
bool isFinished() const
bool isResultReadyAt(int index) const
bool isRunning() const
bool isStarted() const
(since 6.0) bool isSuspended() const
(since 6.0) bool isSuspending() const
(since 6.0) bool isValid() const
(since 6.0) QFuture<T> onCanceled(Function &&handler)
(since 6.1) QFuture<T> onCanceled(QObject *context, Function &&handler)
(since 6.0) QFuture<T> onFailed(Function &&handler)
(since 6.1) QFuture<T> onFailed(QObject *context, Function &&handler)
int progressMaximum() const
int progressMinimum() const
QString progressText() const
int progressValue() const
T result() const
T resultAt(int index) const
int resultCount() const
QList<T> results() const
void resume()
(since 6.0) void setSuspended(bool suspend)
(since 6.0) void suspend()
(since 6.0) T takeResult()
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> then(Function &&function)
(since 6.1) QFuture<QFuture<T>::ResultType<Function>> then(QObject *context, Function &&function)
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> then(QThreadPool *pool, Function &&function)
(since 6.0) QFuture<QFuture<T>::ResultType<Function>> then(QtFuture::Launch policy, Function &&function)
(since 6.0) void toggleSuspended()
(since 6.4) QFuture<U> unwrap()
void waitForFinished()
QFuture<T> &operator=(const QFuture<T> &other)

詳細説明

QFuture は、後の時点で準備が整う 1 つ以上の結果に対してスレッドを同期させることができます。結果は、デフォルト、コピー、および場合によっては移動コンストラクタを持つ任意の型にすることができます。result()、resultAt()、results()、takeResult() 関数を呼び出した時点で結果が利用可能でない場合、QFuture は結果が利用可能になるまで待機します。isResultReadyAt() 関数を使用して、結果の準備ができたかどうかを判断できます。複数の結果を報告する QFuture オブジェクトの場合、resultCount () 関数は、連続した結果の数を返します。つまり、0 からresultCount() までの結果を反復処理することは常に安全です。takeResult() は future を無効にし、その後に result や result from the future にアクセスしようとすると、未定義の動作になります。isValid() は、結果にアクセスできるかどうかを示します。

QFuture には、Java スタイルのイテレータ(QFutureIterator) とSTL スタイルのイテレータ(QFuture::const_iterator) があります。これらのイテレータを使用することも、未来の結果にアクセスする方法の1つです。

ある非同期計算の結果を別の計算に渡す必要がある場合、QFuture はthen() を使って複数の逐次計算を連鎖させる便利な方法を提供します。onCanceled() は、QFuture がキャンセルされたときに呼び出されるハンドラを追加するために使用できます。さらに、onFailed() は、連鎖の中で発生した失敗を処理するために使用できます。QFutureはエラー処理を例外に依存していることに注意してください。例外を使用するオプションがない場合でも、エラー・タイプをQFuture型の一部にすることで、QFutureのエラー状態を示すことができます。例えば、std::variantやstd::anyなどを使って結果や失敗を保持したり、独自の型を作ることができます。

以下の例は、例外を使わずにエラー処理を行う方法を示しています。例えば、ネットワーク上のある場所から大きなファイルを取得するためにネットワークリクエストを送信したいとします。そして、そのファイルをファイルシステムに書き込み、成功した場合にはその場所を返したいとします。これらの操作はどちらも異なるエラーで失敗する可能性がある。そこで、std::variant を使って、結果やエラーを保持する:

using NetworkReply = std::variant<QByteArray, QNetworkReply::NetworkError>;

enum class IOError { FailedToRead, FailedToWrite };
using IOResult = std::variant<QString, IOError>;

そして、then ()を使って、2つの操作を組み合わせる:

QFuture<IOResult> future = QtConcurrent::run([url] {
        ...
        return NetworkReply(QNetworkReply::TimeoutError);
}).then([](NetworkReply reply) {
    if (auto error = std::get_if<QNetworkReply::NetworkError>(&reply))
        return IOResult(IOError::FailedToRead);

    auto data = std::get_if<QByteArray>(&reply);
    // try to write *data and return IOError::FailedToWrite on failure
    ...
});

auto result = future.result();
if (auto filePath = std::get_if<QString>(&result)) {
    // do something with *filePath
else
    // process the error

複数のコンティニュエーションとハンドラーを任意の順序で連結することができる。例えば

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onCanceled([] {
    // Block 2
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

testFuture (キャンセルされた、例外が発生した、結果が出た)の状態に応じて、次のonCanceled ()、onFailed ()、then ()が呼び出される。つまり、testFuture が正常に実行されると、Block 1 が呼び出される。同様に成功すれば、次のthen ()(Block 4 )が呼び出される。testFuture がキャンセルされるか、例外で失敗すると、それぞれBlock 2 またはBlock 3 が呼び出される。その後、次のthen() が呼び出され、話が繰り返される。

注意: Block 2 が呼び出されて例外がスローされた場合、次のonFailed() (Block 3) が処理する。onFailed() とonCanceled() の順序が逆であれば、例外の状態は次の継続に伝搬し、最終的にBlock 5 でキャッチされる。

次の例では、最初のonCanceled() (Block 2) が削除される:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
}).onFailed([] {
    // Block 3
}).then([] {
    // Block 4
}).onFailed([] {
    // Block 5
}).onCanceled([] {
    // Block 6
});

testFuture がキャンセルされると、その状態は次のthen() に伝搬され、これもキャンセルされる。この場合、Block 6 が呼び出される。

未来は1つの継続しか持つことができません。次の例を考えてみよう:

QPromise<int> p;

QFuture<int> f1 = p.future();
f1.then([](int) { qDebug("first"); });

QFuture<int> f2 = p.future();
f2.then([](int) { qDebug("second"); });

p.start();
p.addResult(42);
p.finish();

この場合、f1f2 は同じ内部状態を共有しているので、実質的に同じ QFuture オブジェクトです。その結果、f2then を呼び出すと、f1 で指定された継続が上書きされます。したがって、このコードが実行されると、"second" のみが出力されます。

QFutureは、実行中の計算と対話する方法も提供します。例えば、cancel() 関数で計算をキャンセルできます。計算を中断または再開するには、setSuspended() 関数、またはsuspend()、resume()、toggleSuspended() 便利関数のいずれかを使用します。実行中のすべての非同期計算をキャンセルまたは中断できるわけではないことに注意してください。例えば、QtConcurrent::run() が返す未来はキャンセルできませんが、QtConcurrent::mappedReduced() が返す未来はキャンセルできます。

進捗情報は、progressValue()、progressMinimum()、progressMaximum()、progressText() 関数によって提供されます。waitForFinished() 関数は、呼び出し元のスレッドをブロックして計算の終了を待機させ、すべての結果が利用できるようにします。

QFuture で表される計算の状態は、isCanceled(),isStarted(),isFinished(),isRunning(),isSuspending(),isSuspended() 関数を使用して問い合わせることができる。

QFuture<void> は、結果フェッチ関数を含まないように特化されています。どの QFuture<T> も QFuture<void> に代入またはコピーできます。これは、実際の結果データではなく、ステータスや進捗情報のみが必要な場合に便利です。

シグナルやスロットを使って実行中のタスクとやりとりするには、QFutureWatcher を使います。

また、QtFuture::connect ()を使って、シグナルをQFutureオブジェクトに接続することができます。これにより、QFutureオブジェクトと同じようにシグナルを扱うことができます。例えば、then() と組み合わせると、1つのシグナルに複数の継続をアタッチすることができ、それらは同じスレッドまたは新しいスレッドで呼び出されます。

QtFuture::whenAll() およびQtFuture::whenAny() 関数を使用すると、複数のフューチャーを組み合わせて、それらの最後または最初がいつ完了したかを追跡できます。

値を持つ準備のできた QFuture オブジェクト、または例外を保持する QFuture オブジェクトは、便利関数QtFuture::makeReadyVoidFuture()、QtFuture::makeReadyValueFuture()、QtFuture::makeReadyRangeFuture()、QtFuture::makeExceptionalFuture() を使用して作成できます。

注: いくつかの API(QFuture::then ()またはさまざまなQtConcurrent メソッド・オーバーロードを参照)では、特定のスレッド・プールに計算をスケジューリングすることができます。しかし、QFutureは、デッドロックを防ぎ、スレッド使用を最適化するために、ワーク・ステーリング・アルゴリズムを実装しています。その結果、QFutureの結果を要求するスレッドで直接計算を実行することができます。

注: 計算を開始し、結果を QFuture に格納するには、QPromise またはQt Concurrentフレームワークの API の 1 つを使用します。

QPromiseQtFuture::connect()、QtFuture::makeReadyVoidFuture()、QtFuture::makeReadyValueFuture()、QtFuture::makeReadyRangeFuture()、QtFuture::makeExceptionalFuture()、QFutureWatcher 、およびQt Concurrentも参照してください

メンバ型ドキュメント

QFuture::ConstIterator

QFuture::const_iterator の Qt 形式のシノニム。

メンバ関数ドキュメント

QFuture::QFuture()

キャンセルされた空の未来を構築する。

QFuture::QFuture(const QFuture<T> &other)

other のコピーを作成します。

operator=()も参照してください

QFuture::~QFuture()

未来を破壊する。

これは非同期計算を待機もキャンセルもしないことに注意してください。未来が破棄される前に計算が完了していることを確認する必要がある場合は、waitForFinished() またはQFutureSynchronizer を使用してください。

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::begin() const

future の最初の結果を指すSTL 形式のイテレータを返します。

constBegin() およびend()も参照してください

void QFuture::cancel()

この future で表される非同期計算をキャンセルします。キャンセルは非同期であることに注意してください。同期キャンセルが必要な場合は、cancel() を呼び出した後にwaitForFinished() を使用してください。

現在利用可能な結果は、キャンセルされた未来でもアクセスできますが、この関数を呼び出した後に新しい結果が利用可能になることはありません。このフューチャーをウォッチしているQFutureWatcher オブジェクトは、キャンセルされたフューチャーに対して進行状況と結果の準備完了シグナルを送出しません。

実行中のすべての非同期計算をキャンセルできるわけではないことに注意してください。例えば、QtConcurrent::run() が返す未来はキャンセルできませんが、 QtConcurrent::mappedReduced() が返す未来はキャンセルできます。

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const

未来の最初の結果を指す、STL 形式のイテレータを返します。

begin() およびconstEnd()も参照してください

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const

未来の最後の結果の後の想像上の結果を指す、STL 形式のイテレータを返します。

constBegin() およびend()も参照

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const

未来の最後の結果の後の虚数の結果を指す、STL 形式のconstイテレータを返します。

begin() およびconstEnd()も参照

bool QFuture::isCanceled() const

非同期計算がcancel() 関数でキャンセルされた場合はtrue を返し、そうでない場合はfalse を返す。

そうでない場合はtrue を返します。この関数が を返しても、まだ計算が実行されている可能性があることに注意してください。詳細はcancel() を参照。

bool QFuture::isFinished() const

この future で表される非同期計算が終了した場合はtrue を返し、そうでない場合はfalse を返します。

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture::isResultReadyAt(int index) const

index の結果がすぐに利用できる場合はtrue を返し、そうでない場合はfalse を返します。

注意: isResultReadyAt() を呼び出すと、このQFuture に対してisValid() がfalse を返す場合、未定義の動作になります。

resultAt()、resultCount()、takeResult()も参照

bool QFuture::isRunning() const

この future で表される非同期計算が現在実行中の場合はtrue を返し、そうでない場合はfalse を返す。

bool QFuture::isStarted() const

この未来で表される非同期計算が開始された場合はtrue を返し、そうでない場合はfalse を返します。

[since 6.0] bool QFuture::isSuspended() const

非同期計算の一時停止が要求され、それが有効である場合、つまり、これ以上の結果や進捗の変更が期待されない場合はtrue を返します。

この関数は Qt 6.0 で導入されました。

setSuspended(),toggleSuspended(),isSuspending()も参照してください

[since 6.0] bool QFuture::isSuspending() const

非同期計算がsuspend() 関数で中断されたが、作業がまだ中断されておらず、計算がまだ実行されている場合、true を返します。それ以外の場合はfalse を返す。

サスペンドが実際に有効かどうかを確認するには、代わりにisSuspended() を使用します。

この関数は Qt 6.0 で導入されました。

setSuspended(),toggleSuspended(),isSuspended()も参照してください

[since 6.0] bool QFuture::isValid() const

このQFuture オブジェクトから結果または結果にアクセスまたは取得できる場合、true を返します。結果が未来から取得された後、false を返します。

この関数は Qt 6.0 で導入されました。

takeResult(),result(),results(),resultAt()も参照してください

[since 6.0] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(Function &&handler)

この未来にキャンセルhandler をアタッチします。返された未来は、この未来がキャンセルされない限り、この未来とまったく同じように振る舞います(同じ状態と結果を持ちます)。handler は callable で、引数を取らず、この future がパッケージした型の値を返します。キャンセル後、返された未来はhandler によって返された値をパッケージ化します。

キャンセルの前にアタッチされた場合、handler は、キャンセル後に未来が終了したと報告するのと同じスレッドで呼び出されます。この未来がすでにキャンセルされた後にハンドラがアタッチされた場合、ハンドラはonCanceled() を実行するスレッドで即座に呼び出されます。そのため、ハンドラは常にどのスレッドで実行されるかを想定することはできません。ハンドラがどのスレッドで起動されるかを制御したい場合は、コンテキストオブジェクトを受け取るオーバーロードを使用してください。

以下の例は、キャンセル・ハンドラをアタッチする方法を示している:

QFuture<int> testFuture = ...;
auto resultFuture = testFuture.then([](int res) {
    // Block 1
    ...
    return 1;
}).then([](int res) {
    // Block 2
    ...
    return 2;
}).onCanceled([] {
    // Block 3
    ...
    return -1;
});

testFuture がキャンセルされると、Block 3 が呼び出され、resultFuture はその結果として-1 を持つ。testFuture とは異なり、Canceled の状態にはならない。つまり、その結果を取得したり、カウンティニュエーションをアタッチしたりすることができる。

また、実行中の継続の連鎖は、その連鎖を開始した未来からキャンセルすることができる。例えば、Block 1 の実行中にtestFuture.cancel() が呼ばれたとしよう。次の継続はキャンセルが要求されたことを検出するので、Block 2 はスキップされ、キャンセルハンドラ (Block 3) が呼ばれます。

注意: このメソッドは、継続チェインの結果を表す新しいQFuture を返します。結果のQFuture 自体をキャンセルしても、それにつながるチェーンのキャンセルハンドラは呼び出されません。つまり、resultFuture.cancel() を呼んでも、Block 3 は呼び出されません。resultFuture は、testFuture にキャンセルハンドラをアタッチした結果の未来なので、resultFuture 自体にキャンセルハンドラはアタッチされていません。testFuture のキャンセルか、onCancelled() 呼び出しの前にアタッチされた継続が返すフューチャーのみが、Block 3 をトリガーできます。

この関数は Qt 6.0 で導入されました。

then() とonFailed()も参照してください

[since 6.1] template <typename Function, typename = std::enable_if_t<std::is_invocable_r_v<T, Function>>> QFuture<T> QFuture::onCanceled(QObject *context, Function &&handler)

これはオーバーロードされた関数です。

未来がキャンセルされたときに呼び出されるキャンセルhandler をこの未来にアタッチします。handler は引数を取らない callable です。これはcontext オブジェクトのスレッドで呼び出されます。これは、キャンセルを特定のスレッドで処理する必要がある場合に便利です。

チェーンが終了する前にcontext が破棄されると、未来はキャンセルされます。詳しくはthen() を参照してください。

注意: このメソッドを呼び出すときは、context がチェーンのセットアップ中も生きていることを保証する必要があります。

handler の詳細については、他のオーバーロードのドキュメントを参照してください。

この関数は Qt 6.1 で導入されました。

then() およびonFailed()も参照してください

[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)

例外を処理するために、失敗ハンドラをこの future にアタッチします。返された未来は、この未来が例外で失敗しない限り、この未来とまったく同じように振る舞います(同じ状態と結果を持ちます)。

handler は callable で、引数なし、または引数を1つ取り、catchステートメントと同様に、特定のエラー・タイプでフィルタリングします。これは、このfutureによってパッケージ化された型の値を返します。失敗の後、返されたfutureはhandler によって返された値をパッケージします。

ハンドラは、例外が発生した場合にのみ呼び出されます。このハンドラがアタッチされた後に例外が発生した場合、ハンドラは、例外の結果として future が終了したと報告したスレッドで実行されます。もしこのハンドラが、この未来がすでに失敗した後にアタッチされた場合、ハンドラはonFailed() を実行するスレッドで即座に呼び出されます。したがって、ハンドラは常にどのスレッドで実行されるかを想定することはできません。ハンドラがどのスレッドで起動されるかを制御したい場合は、コンテキストオブジェクトを受け取るオーバーロードを使用してください。

以下の例は、失敗ハンドラをアタッチする方法を示しています:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error();
    ...
}).onFailed([](const Error &e) {
    // Handle exceptions of type Error
    ...
    return -1;
}).onFailed([] {
    // Handle all other types of errors
    ...
    return -1;
});

auto result = resultFuture.result(); // result is -1

複数のハンドラがアタッチされている場合、スローされた例外の型にマッチする最初のハンドラが起動されます。例えば

QFuture<int> future = ...;
future.then([](int res) {
    ...
    throw std::runtime_error("message");
    ...
}).onFailed([](const std::exception &e) {
    // This handler will be invoked
}).onFailed([](const std::runtime_error &e) {
    // This handler won't be invoked, because of the handler above.
});

どのハンドラもスローされた例外の型と一致しない場合、例外は結果のフューチャーに伝搬されます:

QFuture<int> future = ...;
auto resultFuture = future.then([](int res) {
    ...
    throw Error("message");
    ...
}).onFailed([](const std::exception &e) {
    // Won't be invoked
}).onFailed([](const QException &e) {
    // Won't be invoked
});

try {
    auto result = resultFuture.result();
} catch(...) {
    // Handle the exception
}

注意: すべての例外タイプを処理し、try-catch ブロックを書かなくて済むように、常に引数を取らないハンドラをアタッチすることができます。

この関数は Qt 6.0 で導入されました。

then() およびonCanceled()も参照してください

[since 6.1] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(QObject *context, Function &&handler)

これはオーバーロードされた関数です。

失敗ハンドラをこの future にアタッチし、future が発生させる例外や、すでに発生させた例外を処理します。この future と同じ型のQFuture を返します。ハンドラは、context オブジェクトのスレッドで例外が発生した場合にのみ呼び出されます。これは、失敗を特定のスレッドで処理する必要がある場合に便利です。例えば

// somewhere in the main thread
auto future = QtConcurrent::run([] {
    // This will run in a separate thread
    ...
    throw std::exception();
}).onFailed(this, [] {
   // Update UI elements
});

QtConcurrent::run にアタッチされた失敗ハンドラはUIエレメントを更新するので、gui以外のスレッドから呼び出すことはできません。そこで、this.onFailed() のコンテキストとして提供し、メインスレッドで起動されるようにします。

チェーンが終了する前にcontext が破棄されると、未来はキャンセルされます。詳細はthen() を参照。

注意: このメソッドを呼び出すときは、context がチェーンのセットアップ中も生きていることを保証する必要があります。

handler の詳細については、他のオーバーロードのドキュメントを参照してください。

この関数は Qt 6.1 で導入されました。

then() およびonCanceled()も参照してください

int QFuture::progressMaximum() const

progressValue() の最大値を返します。

progressValue() およびprogressMinimum() も参照

int QFuture::progressMinimum() const

最小値progressValue() を返します。

progressValue() およびprogressMaximum() も参照

QString QFuture::progressText() const

非同期計算によって報告された進捗のテキスト表現(オプション)を返します。

すべての計算が進捗のテキスト表現を提供するとは限らないので、この関数は空の文字列を返す可能性があることに注意してください。

int QFuture::progressValue() const

progressMinimum() とprogressMaximum() の間にある現在の進捗値を返す。

progressMinimum() およびprogressMaximum()も参照のこと

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::result() const

未来の最初の結果を返す。結果がすぐに利用できない場合、この関数はブロックして結果が利用可能になるのを待ちます。これは、resultAt(0)を呼び出すための便利なメソッドである。result() は、内部に格納された結果のコピーを返すことに注意。T が移動専用型である場合、または結果をコピーしたくない場合は、代わりにtakeResult() を使用する。

注意: isValid() がこのQFuture に対してfalse を返す場合、result() を呼び出すと未定義の動作になる。

resultAt()、results()、takeResult()も参照

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const

将来のindex での結果を返す。結果がすぐに利用可能でない場合、この関数はブロックして、結果が利用可能になるのを待ちます。

注意: isValid() がこのQFuture に対してfalse を返す場合、resultAt() を呼び出すと未定義の動作になる。

result()、results()、takeResult()、resultCount()も参照

int QFuture::resultCount() const

この未来で利用可能な連続結果の数を返します。結果セットにずれがあるため、実際に格納される結果の数はこの値と異なる可能性があります。0からresultCount()までの結果を繰り返し処理するのが常に安全です。

result()、resultAt()、results()、takeResult()も参照

template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QList<T> QFuture::results() const

未来からのすべての結果を返す。結果がすぐに利用できない場合、この関数はブロックして利用可能になるのを待つ。results() は、内部的に保存された結果のコピーを返すことに注意。移動のみのタイプT のすべての結果を取得することは、現時点ではサポートされていません。しかし、STLスタイルのイテレータや読み取り専用のJavaスタイルのイテレータを使用することで、移動のみの結果のリストを繰り返し処理することは可能です。

注: isValid() がこのQFuture に対してfalse を返す場合、results() を呼び出すと未定義の動作になる。

result()、resultAt()、takeResult()、resultCount()、isValid()も参照のこと

void QFuture::resume()

future() で表される非同期計算を再開する。これは、setSuspended(false)を呼び出すだけの便利なメソッドです。

suspend()も参照

[since 6.0] void QFuture::setSuspended(bool suspend)

suspend が true の場合、この関数は future() で表される非同期計算を一時停止します。すでに計算が中断されている場合、この関数は何もしません。QFutureWatcher は、future が中断されても、直ちに進行状況シグナルと結果準備完了シグナルの配信を停止するわけではありません。中断された時点では、まだ進行中の計算があり、それを停止することはできません。そのような計算のシグナルはまだ配信されます。

suspend が false の場合、この関数は非同期計算を再開する。計算が中断されていない場合、この関数は何もしない。

すべての計算を中断できるわけではないことに注意してください。例えば、QtConcurrent::run() が返すQFuture は中断できませんが、QtConcurrent::mappedReduced() が返すQFuture は中断できます。

この関数は Qt 6.0 で導入されました。

isSuspended(),suspend(),resume(),toggleSuspended()も参照してください

[since 6.0] void QFuture::suspend()

この future で表される非同期計算を一時停止します。これはsetSuspended(true) を呼び出すだけの便利なメソッドです。

この関数は Qt 6.0 で導入されました。

resume()も参照してください

[since 6.0] template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::takeResult()

この関数は、isValid() がtrue を返す場合にのみ呼び出します。この関数は、QFuture オブジェクトから最初の結果を取ります(移動します)。他の結果がある場合は、最初の結果を取得した後に破棄されます。結果がすぐに利用できない場合、この関数はブロックして結果が利用できるようになるのを待ちます。QFuture は、可能であればムーブ・セマンティクスを使おうとし、型がムーバブルでない場合はコピー・コンストラクションにフォールバックする。結果が取得された後、isValid ()はfalse として評価される。

注: QFuture は一般的に、異なるQFuture オブジェクト間で(そして潜在的に異なるスレッド間で)結果を共有することができる。takeResult() は、QFuture が(std::unique_ptr のような)移動専用の型でも動作するようにするために導入された。そのため、1つのスレッドだけが結果を未来から移動させることができ、それを一度だけ実行することを想定している。また、すべての結果のリストを取ることは今のところサポートされていないことに注意してください。しかし、STLスタイルのイテレータや読み取り専用のJavaスタイルのイテレータを使うことで、移動のみの結果のリストを繰り返し処理することはできます。

この関数は Qt 6.0 で導入されました。

result(),results(),resultAt(),isValid()も参照してください

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)

これはオーバーロードされた関数です。

この future に継続をアタッチし、必要であればSync ポリシーを使用して複数の非同期計算を連鎖させることができます。function は callable で、この future が結果を持つ場合(QFuture<void> ではない場合)、この future がパッケージ化した型の引数を取ります。そうでない場合は引数を取りません。このメソッドはfunction によって返された型の値をパッケージ化した新しいQFuture を返します。返された future は、アタッチされた継続が呼び出されるか、この future が失敗するかキャンセルされるまで、初期化されていない状態になります。

注意: 継続を別のスレッドで起動する必要がある場合は、このメソッドの他のオーバーロードを使用します。

このように複数の操作を連鎖させることができます:

QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...

または

QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...

Or:継続はQFuture の引数を取ることもできる(値の代わりに)。これは、例えばQFuture が複数の結果を持っていて、ユーザが継続の内部でそれらにアクセスしたい場合に便利である。あるいは、複数の継続の連鎖を妨げないように、継続の内部で前の未来の例外を処理する必要があります。例えば

QFuture<int> future = ...;
    future.then([](QFuture<int> f) {
        try {
            ...
            auto result = f.result();
            ...
        } catch (QException &e) {
            // handle the exception
        }
    }).then(...);

前の未来が例外をスローし、それが継続の内部で処理されない場合、呼び出し元が例外を処理できるように、例外は継続の未来に伝搬されます:

QFuture<int> future = ...;
auto continuation = future.then([](int res1){ ... }).then([](int res2){ ... })...
...
// future throws an exception
try {
    auto result = continuation.result();
} catch (QException &e) {
    // handle the exception
}

この場合、継続のチェーン全体が中断されます。

注意: この未来がキャンセルされると、その未来に接続されている継続もキャンセルされます。

この関数はQt 6.0で導入されました。

onFailed() とonCanceled()も参照してください

[since 6.1] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QObject *context, Function &&function)

これはオーバーロードされた関数です。

必要に応じて複数の非同期計算を連鎖させることができます。この future が表す非同期計算が終了すると、context オブジェクトのスレッドでfunction が呼び出されます。これは、継続を特定のスレッドで呼び出す必要がある場合に便利です。例えば

// somewhere in the main thread
auto future = QtConcurrent::run([] {
    // This will run in a separate thread
    ...
}).then(this, [] {
   // Update UI elements
});

QtConcurrent::run にアタッチされた継続は UI 要素を更新するので、gui 以外のスレッドから呼び出すことはできない。そこで、this.then() のコンテキストとして提供し、メインスレッドで呼び出されるようにする。

異なるコンテキストや起動ポリシーが指定されない限り、以下の継続も同じコンテキストから起動される:

auto future = QtConcurrent::run([] {
    ...
}).then(this, [] {
   // Update UI elements
}).then([] {
    // This will also run in the main thread
});

これは、デフォルトでは.then() が前のスレッドと同じスレッドから呼び出されるためである。

しかし、この未来がすでに終了した後に継続がアタッチされた場合、then() を実行するスレッドですぐに呼び出されることに注意してください:

QObject *context = ...;
auto future = cachedResultsReady ? QtFuture::makeReadyValueFuture(result)
                                 : QtConcurrent::run([] { /* compute result */});
auto continuation = future.then(context, [] (Result result) {
    // Runs in the context's thread
}).then([] {
    // May or may not run in the context's thread
});

上記の例で、cachedResultsReadytrue で、準備完了の未来が返された場合、最初の.then() が2番目の未来がアタッチされる前に終了する可能性があります。この場合、現在のスレッドで解決されます。したがって、疑わしい場合は、コンテキストを明示的に渡してください。

チェーンが終了する前にcontext が破棄された場合、未来はキャンセルされます。これは、context が有効でなくなったときにキャンセル・ハンドラが呼び出される可能性があることを意味します。これを防ぐには、contextQPointer としてキャプチャします:

QObject *context = ...;
auto future = ...;
auto continuation = future.then(context, [context](Result result) {
                               // ...
                           }).onCanceled([context = QPointer(context)] {
                               if (!context)
                                   return;  // context was destroyed already
                               // handle cancellation
                           });

コンテキスト・オブジェクトが破棄されると、直ちにキャンセルが行われる。コンテクストオブジェクトが破棄されると、即座にキャンセルされる。チェイン内の前のフューチャーはキャンセルされず、終了するまで実行され続ける。

注意: このメソッドを呼び出すときは、context がチェーンのセットアップ中も生きていることを保証しなければならない。

この関数は Qt 6.1 で導入されました。

onFailed() およびonCanceled()も参照してください

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QThreadPool *pool, Function &&function)

これはオーバーロードされた関数です。

必要に応じて複数の非同期計算を連鎖させることができます。この future で表される非同期計算が終了すると、poolfunction がスケジューリングされます。

この関数は Qt 6.0 で導入されました。

onFailed() とonCanceled()も参照してください

[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(QtFuture::Launch policy, Function &&function)

これはオーバーロードされた関数です。

複数の非同期計算を連鎖させることができるように、この future に継続をアタッチします。この future で表される非同期計算が終了すると、与えられた launchpolicy に従ってfunction が呼び出されます。継続の結果を表す新しいQFuture が返されます。

policy に応じて、継続はこの future と同じスレッド、新しいスレッド、またはこの future の起動ポリシーとスレッドプールを継承して起動されます。起動ポリシーが指定されていない場合 (callable を取るオーバーロードを参照)、Sync のポリシーが使用されます。

次の例では、両方の継続が新しいスレッド(ただし同じスレッド)で起動されます。

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... }).then([](int res2){ ... });

次の例では、両方の継続は、同じスレッドプールを使用する新しいスレッドで起動されます。

QFuture<int> future = ...;
future.then(QtFuture::Launch::Async, [](int res){ ... })
      .then(QtFuture::Launch::Inherit, [](int res2){ ... });

function の詳細については、もう一方のオーバーロードのドキュメントを参照してください。

この関数は Qt 6.0 で導入されました。

onFailed() およびonCanceled()も参照してください

[since 6.0] void QFuture::toggleSuspended()

非同期計算のサスペンド状態を切り替えます。言い換えると、計算が現在サスペンド中または中断中の場合、この関数を呼び出すと再開されます。これはsetSuspended(!(isSuspending() ||isSuspended())) を呼び出すための便利なメソッドである。

この関数は Qt 6.0 で導入されました。

setSuspended(),suspend(),resume()も参照してください

[since 6.4] template <typename U> QFuture<U> QFuture::unwrap()

このQFuture<T> から内側の未来を解き放ちます。ここで、TQFuture<U> 型の未来、つまり、この未来はQFuture<QFuture<U>> 型を持ちます:

QFuture<QFuture<int>> outerFuture = ...;
QFuture<int> unwrappedFuture = outerFuture.unwrap();

unwrappedFuture は、 の中に入れ子になっている内側の未来が、同じ結果または例外で、内側の未来が終了したと報告したスレッドで満たされると同時に満たされます。内側の未来がキャンセルされると、 もキャンセルされます。outerFuture unwrappedFuture

これは、複数の計算を連鎖させ、そのうちの1つが結果型としてQFuture を返す場合に特に便利です。例えば、URL から複数の画像をダウンロードし、画像を拡大縮小し、QtConcurrent::mappedReduced() を使用して 1 つの画像に縮小したいとします。次のように書くことができます:

auto downloadImages = [] (const QUrl &url) {
    QList<QImage> images;
    ...
    return images;
};

auto processImages = [](const QList<QImage> &images) {
   return QtConcurrent::mappedReduced(images, scale, reduceImages);
}

auto show = [](const QImage &image) { ... };

auto future = QtConcurrent::run(downloadImages, url)
               .then(processImages)
               .unwrap()
               .then(show);

ここで、QtConcurrent::mappedReduced()QFuture<QImage> を返すので、.then(processImages)QFuture<QFuture<QImage>> を返します。show() は引数としてQImage を取るので、.then(processImages) の結果を直接渡すことはできません。.unwrap() を呼び出す必要がある。 は、準備ができたら内側の未来の結果を取得し、それを次の継続に渡す。

複数のネストがある場合、.unwrap() は最も内側のレベルに降りていきます:

QFuture<QFuture<QFuture<int>>>> outerFuture;
QFuture<int> unwrappedFuture = outerFuture.unwrap();

この関数は Qt 6.4 で導入されました。

void QFuture::waitForFinished()

非同期計算(cancel ()された計算を含む)が終了するまで、つまりisFinished ()がtrue を返すまで待つ。

QFuture<T> &QFuture::operator=(const QFuture<T> &other)

other をこの future に割り当て、この future への参照を返します。

本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。