QFuture Class
template <typename T> class QFutureQFuture 类表示异步计算的结果。更多内容...
| 头文件: | #include <QFuture> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS Core) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
- 所有成员的列表,包括继承的成员
- 已弃用的成员
- QFuture 属于线程类。
注意:该类中的所有函数均是线程安全的,但以下情况除外:
公共类型
| class | const_iterator |
| ConstIterator |
公共函数
| QFuture() | |
| QFuture(const QFuture<T> &other) | |
| ~QFuture() | |
| QFuture<T>::const_iterator | begin() const |
| void | cancel() |
(since 6.10) void | cancelChain() |
| 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 是一个模板类,其中模板参数T 指定了异步计算所产生的结果类型。
QFuture 允许线程针对一个或多个将在稍后时间点准备就绪的结果进行同步。结果可以是任何具有默认构造函数、复制构造函数以及(可能)移动构造函数的类型。 如果在调用result()、resultAt()、results() 和takeResult() 函数时结果尚不可用,QFuture 将等待直到结果可用。您可以使用isResultReadyAt() 函数来确定结果是否已准备就绪。对于报告多个结果的 QFuture 对象,resultCount() 函数将返回连续结果的数量。 这意味着,从 0 开始遍历结果直至调用resultCount() 始终是安全的。takeResult() 会使未来对象失效,此后任何尝试访问该未来对象的结果的行为都将导致未定义行为。isValid() 可告知您是否可以访问结果。
QFuture 提供了一个Java 风格的迭代器(QFutureIterator )和一个STL 风格的迭代器(QFuture::const_iterator )。使用这些迭代器是访问未来结果的另一种方式。
如果需要将一个异步计算的结果传递给另一个异步计算,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()` 将这两项操作组合起来:
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 = someIntFuture;
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 = someIntFuture;
auto resultFuture = testFuture.then([](int res) {
// Block 1
}).onFailed([] {
// Block 3
}).then([] {
// Block 4
}).onFailed([] {
// Block 5
}).onCanceled([] {
// Block 6
});如果testFuture 被取消,其状态将传播到下一个then(),该 () 也会被取消。因此,在此情况下将调用Block 6 。
一个未来对象只能有一个延续。请看以下示例:
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();在此情况下,f1 和f2 实际上是同一个 QFuture 对象,因为它们共享相同的内部状态。因此,在f2 上调用then 将覆盖为f1 指定的延续。所以,执行此代码时只会打印"second" 。
QFuture 还提供了与正在运行的计算交互的方法。例如,可以使用cancel() 函数取消计算。要暂停或恢复计算,请使用setSuspended() 函数,或使用suspend()、resume() 或toggleSuspended() 中的任意一个便捷函数。 请注意,并非所有正在运行的异步计算都可以被取消或暂停。例如,QtConcurrent::run() 返回的 Future 无法被取消;但 QtConcurrent::mappedReduced() 返回的 Future 则可以。
进度信息可通过progressValue()、progressMinimum()、progressMaximum() 和progressText() 函数获取。waitForFinished() 函数会使调用线程阻塞并等待计算完成,从而确保所有结果均已就绪。
可以通过isCanceled()、isStarted()、isFinished()、isRunning()、isSuspending() 或isSuspended() 函数查询由 QFuture 表示的计算状态。
QFuture<void> 经过特化处理,不包含任何结果获取函数。任何 QFuture<T> 都可以被赋值或复制到 QFuture<void> 中。当仅需状态或进度信息(而非实际结果数据)时,此特性非常有用。
若要通过信号和槽与正在运行的任务进行交互,请使用QFutureWatcher 。
您还可以使用 `QtFuture::connect()` 将信号连接到 `QFuture` 对象,该对象将在信号发出时被解析。这使得您可以像操作 `QFuture` 对象一样操作信号。例如,如果将其与 `then()` 结合使用,您可以将多个延续函数附加到一个信号上,这些延续函数将在同一线程或新线程中被调用。
QtFuture::whenAll() 和QtFuture::whenAny() 函数可用于组合多个未来对象,并跟踪其中最后一个或第一个完成的时间。
可以使用便捷函数QtFuture::makeReadyVoidFuture()、QtFuture::makeReadyValueFuture()、QtFuture::makeReadyRangeFuture() 和QtFuture::makeExceptionalFuture() 来创建一个带有值的就绪 QFuture 对象,或者一个包含异常的 QFuture 对象。
注意:某些 API(参见QFuture::then() 或各种QtConcurrent 方法的重载)允许将计算调度到特定的线程池中。但是,QFuture 实现了工作窃取算法,以防止死锁并优化线程使用。因此,计算可以直接在请求 QFuture 结果的线程中执行。
注意:若要 启动计算并将结果存储在 QFuture 中,请使用QPromise 或 Qt Concurrent 框架中的 API 之一。
另请参阅 QPromise 、QtFuture::connect()、QtFuture::makeReadyVoidFuture()、QtFuture::makeReadyValueFuture()、QtFuture::makeReadyRangeFuture()、QtFuture::makeExceptionalFuture()、QFutureWatcher 以及 Qt Concurrent。
成员函数文档
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
返回一个指向未来对象中第一个结果的常量STL 风格迭代器。
另请参阅 constBegin() 和end()。
void QFuture::cancel()
取消由该未来对象所代表的异步计算。请注意,取消操作本身也是异步的。若需要同步取消,请在调用 cancel() 之后使用waitForFinished()。
对于已被取消的 Future,仍可访问当前已有的结果,但在调用此函数后将不会有新的结果产生。任何监听此 Future 的QFutureWatcher 对象,在该 Future 被取消后都不会发送进度和结果就绪信号。
请注意,并非所有正在运行的异步计算都可以被取消。例如,QtConcurrent::run() 返回的 Future 无法被取消;但 QtConcurrent::mappedReduced() 返回的 Future 则可以被取消。
另请参阅 cancelChain()。
[since 6.10] void QFuture::cancelChain()
取消整个延续链。所有已完成的未来对象保持不变,其结果仍然可用。每个待处理的延续都会被取消,如果延续链中存在onCanceled()处理程序,则会调用该处理程序。
auto f = QtConcurrent::run([] {/*...*/})
.then([]{
// Then 1
})
.then([]{
// Then 2
})
.onCanceled([]{
// OnCanceled 1
})
.then([]{
// Then 3
})
.then([]{
// Then 4
})
.onCanceled([]{
// OnCanceled 2
});
//...
f.cancelChain();在示例中,如果链在 `Then 2 ` 延续执行之前被取消,则 `OnCanceled 1 ` 和 `OnCanceled 2 ` 两个取消处理程序都会被调用。
如果链在Then 2 之后、但Then 4 之前被取消,则仅会调用OnCanceled 2 。
注意:当 对已经完成的未来对象调用此方法时 ,该方法无效。建议如上例所示,对代表整个延续链的QFuture 对象使用此方法。
如果链中的任何延续执行了异步计算并返回了一个表示该计算的QFuture ,那么一旦该嵌套计算开始,cancelChain() 的调用将不会传播到该嵌套计算中。 原因在于:该未来对象只有在外层未来对象完成时才会出现在延续链中,但取消操作可能发生在外层和嵌套的未来对象都在等待其计算完成之时。在这种情况下,需要显式捕获并取消该嵌套的未来对象。
QFuture<void> nested;
auto f = createFuture()
.then([&]{
nested = runNestedComputation();
// do some other work
return nested;
})
.unwrap()
.then([]{
// other continuation
})
.onCanceled([]{
// handle cancellation
});
//...
f.cancelChain();
nested.cancel();在此示例中,如果 `runNestedComputation() ` 已处于执行中,则只能通过调用 `nested.cancel()` 来取消它。
该函数在 Qt 6.10 中引入。
另请参阅 cancel()。
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constBegin() const
返回一个指向未来对象中第一个结果的常量STL 风格迭代器。
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::constEnd() const
返回一个指向未来中最后一个结果之后的虚拟结果的、STL 风格的const迭代器。
另请参阅 constBegin() 和end()。
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> QFuture<T>::const_iterator QFuture::end() const
返回一个常量STL 风格的迭代器,该迭代器指向未来中最后一个结果之后的虚拟结果。
bool QFuture::isCanceled() const
如果异步计算已被通过cancel()函数取消,则返回true ;否则返回false 。
请注意,即使该函数返回true ,计算仍可能仍在进行中。更多详细信息请参阅cancel()。
bool QFuture::isFinished() const
如果由该未来对象表示的异步计算已完成,则返回true ;否则返回false 。
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> bool QFuture::isResultReadyAt(int index) const
如果index 上的结果立即可用,则返回true ;否则返回false 。
注意: 如果isValid() 对于此QFuture 返回false ,则调用此 函数会导致未定义行为。如果此QFuture 尚未启动,请在调用此函数之前先调用waitForFinished(),以避免未定义行为。
另请参阅 resultAt()、resultCount() 和takeResult()。
bool QFuture::isRunning() const
如果由该未来对象表示的异步计算当前正在运行,则返回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 。如果相关的QPromise 尚未开始,或者结果已从该未来对象中收集,则返回false 。
注意: 该函数的返回值 仅表示未来结果是否可被消耗,而非是否已就绪。当相关的QPromise 已启动,但结果尚未就绪时,该函数将返回true 。若要检测就绪状态,请调用isResultReadyAt() 或isFinished()。
该函数在 Qt 6.0 中引入。
另请参阅 takeResult()、result()、results()、resultAt()、isFinished() 以及isResultReadyAt()。
[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 ` 是一个不带参数的可调用对象,其返回值类型由该未来对象封装。取消后,返回的未来对象将封装由 `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 中引入。
[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 ` 是一个不接受任何参数的可调用对象。它将在 `context ` 对象所属的线程中被调用。如果需要在特定线程中处理取消操作,这将非常有用。
如果context 在链完成之前被销毁,则该Future将被取消。详情请参阅then()。
注意: 调用此方法时 ,应确保在链的设置过程中context 保持存活。
有关 `handler` 的更多详细信息,请参阅其他重载版本的文档。
这是一个重载函数。
此函数在 Qt 6.1 中引入。
[since 6.0] template <typename Function, typename = std::enable_if_t<!QtPrivate::ArgResolver<Function>::HasExtraArgs>> QFuture<T> QFuture::onFailed(Function &&handler)
将一个故障处理程序附加到此未来对象上,用于处理任何异常。返回的未来对象的行为与该未来对象完全一致(具有相同的状态和结果),除非该未来对象因异常而失败。
handler 是一个可调用对象,它既可以不带参数,也可以带一个参数,用于根据特定的错误类型进行过滤,类似于catch语句。它返回一个由该 Future 封装的类型的值。失败发生后,返回的 Future 会将handler 返回的值进行封装。
只有当抛出异常时,处理程序才会被调用。如果异常是在此处理程序附加之后抛出的,则该处理程序将在因异常导致该未来被报告为已完成的那条线程中执行。 如果处理程序是在该未来对象已经失败后附加的,它将立即在执行 `onFailed()` 的线程中被调用。因此,处理程序不能总是假设它将在哪个线程上运行。若要控制处理程序在哪个线程上被调用,请使用接受上下文对象的重载版本。
下面的示例演示了如何挂接失败处理程序:
QFuture<int> future = someIntFuture;
auto resultFuture = future.then([](int res) {
//...
throw Error();
//...
return res;
}).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 = someIntFuture;
future.then([](int res) {
//...
throw std::runtime_error("message");
//...
}).onFailed([](const std::exception &e) {
// This handler will be invoked
return -1;
}).onFailed([](const std::runtime_error &e) {
// This handler won't be invoked, because of the handler above.
return -1;
});如果没有任何一个处理程序与抛出的异常类型匹配,则该异常将传播到结果 Future:
QFuture<int> future = someIntFuture;
auto resultFuture = future.then([](int res) {
//...
throw Error("message");
//...
return res;
}).onFailed([](const std::exception &e) {
// Won't be invoked
return -1;
}).onFailed([](const QException &e) {
// Won't be invoked
return -1;
});
try {
auto result = resultFuture.result();
} catch(QException &someException) {
// 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)
将一个故障处理程序附加到该未来对象上,用于处理该未来对象可能抛出的或已经抛出的任何异常。返回一个与该未来对象类型相同的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 在链处理完成前被销毁,则该Future将被取消。详情请参阅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 ,则调用 此函数将导致未定义行为。如果此QFuture 尚未启动,请在调用此函数之前先调用waitForFinished(),以避免未定义行为。
另请参阅 resultAt()、results() 和takeResult()。
template <typename U = T, typename = QtPrivate::EnableForNonVoid<U>> T QFuture::resultAt(int index) const
返回未来时间点index 处的结果。如果结果无法立即获取,该函数将阻塞并等待结果可用。
注意: 如果对于此QFuture ,isValid() 返回false ,则调用此 函数将导致未定义的行为。如果此QFuture 尚未启动,请在调用此函数之前先调用waitForFinished(),以避免未定义的行为。
另请参阅 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 风格迭代器遍历仅移动型结果列表。
注意: 如果对于此QFuture ,isValid() 返回false ,则调用此 函数将导致未定义行为。如果此QFuture 尚未启动,请在调用此函数之前先调用waitForFinished(),以避免未定义行为。
另请参阅 result()、resultAt()、takeResult()、resultCount() 和isValid()。
void QFuture::resume()
恢复由 future() 表示的异步计算。这是一个便捷方法,仅调用setSuspended(false)。
另请参阅 suspend()。
[since 6.0] void QFuture::setSuspended(bool suspend)
如果 `suspend ` 为真,则该函数会挂起由 `future()` 表示的异步计算。如果计算已被挂起,则该函数不执行任何操作。当 `future` 被挂起时,`QFutureWatcher ` 不会立即停止发送进度和结果就绪信号。 在暂停的瞬间,可能仍有正在进行且无法停止的计算。此类计算的信号仍会继续被分发。
如果suspend 为 false,则该函数将恢复异步计算。如果计算此前未被暂停,则该函数不执行任何操作。
请注意,并非所有计算都可以被暂停。例如,QtConcurrent::run() 返回的QFuture 无法被暂停;但 QtConcurrent::mappedReduced() 返回的QFuture 则可以。
该函数在 Qt 6.0 中引入。
另请参阅 isSuspended()、suspend()、resume() 和toggleSuspended()。
[since 6.0] void QFuture::suspend()
暂停由该未来对象所表示的异步计算。这是一个便捷方法,仅调用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)配合使用,因此它假设只有一个线程可以将结果从未来对象中移出,且仅执行一次。 另请注意,目前尚不支持获取所有结果的列表。不过,您仍可使用STL 风格的迭代器或Java 风格的只读迭代器遍历仅支持移动操作的结果列表。
该函数在 Qt 6.0 中引入。
另请参阅 result()、results()、resultAt() 以及isValid()。
[since 6.0] template <typename Function> QFuture<QFuture<T>::ResultType<Function>> QFuture::then(Function &&function)
将一个延续附加到此未来对象上,从而允许在需要时使用Sync 策略将多个异步计算串联起来。function 是一个可调用对象,如果该未来对象有结果(即不是QFuture<void>),则它会接受一个由该未来对象封装的类型的参数。 否则,它不接受任何参数。该方法返回一个新的QFuture ,该对象封装了由function 返回的类型的值。返回的Future将处于未初始化状态,直到附加的延续被调用,或者直到该Future失败或被取消。
注意: 若需在单独的线程中启动延续,请使用 该方法的其他重载。
您可以像这样链式调用多个操作:
QFuture<int> future = ...;
future.then([](int res1){ ... }).then([](int res2){ ... })...或者:
QFuture<void> future = ...;
future.then([](){ ... }).then([](){ ... })...延续还可以接受一个QFuture 类型的参数(而非其值),该参数代表前一个未来对象。例如,当QFuture 返回多个结果,且用户希望在延续内部访问这些结果时,此功能便十分有用。或者,当用户需要在延续内部处理前一个未来对象的异常,以避免中断多个延续的链式调用时,此功能同样适用。例如:
QFuture<int> future = someIntFuture;
future.then([](QFuture<int> f) {
try {
//...
auto result = f.result();
//...
} catch (QException &e) {
// handle the exception
}
}).then([](){/*...*/});警告:如果 前一个 Future 包含多个类型为T 的结果,且延续函数将类型为T 的参数作为参数接收,则延续函数中仅会处理前一个QFuture 的第一个结果!
如果前一个未来对象抛出了异常,且该异常未在延续内部被处理,则该异常将传播到延续的未来对象中,以便调用方进行处理:
QFuture<int> future = someIntFuture;
auto continuation = future.then([](int res1){ /*...*/ return res1; }).then([](int res2){ /*...*/ return 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)
将一个延续附加到此未来对象上,从而可在需要时将多个异步计算串联起来。当此未来对象所代表的异步计算完成时,将在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::makeReadyVoidFuture()
: QtConcurrent::run([] { /* compute result */});
auto continuation = future.then(context, [] {
// Runs in the context's thread
}).then([] {
// May or may not run in the context's thread
});在上例中,如果 `cachedResultsReady ` 为 `true`,且返回了一个已就绪的未来,那么第一个 `.then() ` 可能在第二个被附加之前就已完成。在这种情况下,它将在当前线程中被解析。因此,如有疑问,请显式传递上下文。
如果context 在链完成之前被销毁,则该Future将被取消。这意味着,当context 不再有效时,取消处理程序仍可能被调用。为防范这种情况,请将context 捕获为QPointer :
QObject *context /*...*/;
QFuture<Result> 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)
将一个延续附加到此未来对象上,以便在需要时串联多个异步计算。当此未来对象所代表的异步计算完成时,function 将被调度到pool 上。
这是一个重载函数。
该函数在 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 所代表的异步计算完成时,将根据给定的启动策略policy 调用function 。返回一个表示该延续结果的新QFuture 。
根据policy 的不同,延续将在与该 Future 相同的主线程中、在新主线程中被调用,或者继承该 Future 的启动策略和线程池。如果未指定启动策略(参见仅接受可调用对象的重载),则将使用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> 中解包内部Future,其中T 是一个类型为QFuture<U> 的Future,即该Future的类型为QFuture<QFuture<U>> 。例如:
unwrappedFuture 一旦嵌套在outerFuture 中的内部未来完成,该操作即刻完成,其结果或异常与内部未来相同,且在报告内部未来已完成的同一线程中执行。如果内部未来被取消,unwrappedFuture 也会被取消。
当链式调用多个计算操作,且其中一个操作返回 `QFuture ` 作为结果类型时,这尤其有用。例如,假设我们想要从一个 URL 下载多张图片,对图片进行缩放,并使用 `QtConcurrent::mappedReduced()` 将其合并为单张图片。我们可以这样编写代码:
auto downloadImages = [] (const QUrl &url) {
QList<QImage> images;
//...
return images;
};
auto processImages = [scale, reduceImages](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() 会深入到最内层:
该函数在 Qt 6.4 中引入。
void QFuture::waitForFinished()
等待异步计算完成(包括调用cancel()的计算),即直到isFinished()返回true 。
QFuture<T> &QFuture::operator=(const QFuture<T> &other)
将other 赋值给该未来对象,并返回该未来对象的引用。
© 2026 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.