本页内容

并发任务

QtConcurrent::task 提供了一种在单独线程中运行任务的替代接口。该函数的返回值可通过QFuture API获取。

若您仅需在单独线程中运行函数且无需调整任何参数,请使用QtConcurrent::run ,这样可以减少代码量。QtConcurrent::task 专为需要执行额外配置步骤的情况而设计。

该函数是 Qt Concurrent 框架的一部分。

优化包含

如果您包含<QtConcurrent> 头文件,整个Qt Concurrent 模块以及完整的Qt Core 模块都会被包含进来,这可能会增加编译时间和二进制文件的大小。要使用QtConcurrent::task() 函数,您可以包含一个更具体的头文件:

#include <QtConcurrentTask>

流式接口

QtConcurrent::task 会返回一个名为QtConcurrent::QTaskBuilder 的辅助类的实例。通常情况下,您无需手动创建该类的实例。QtConcurrent::QTaskBuilder 提供了一个接口,可像链式调用一样调整不同的任务参数。这种方法被称为流畅接口。

您只需设置所需的参数,然后即可启动任务。为了最终确定任务的配置,您必须调用QtConcurrent::QTaskBuilder::spawn 。该函数是非阻塞的(即立即返回一个未来对象),但不能保证任务会立即开始。 您可以使用QFuture 和QFutureWatcher 类来监控任务的状态。

请参阅下文中的更多示例和说明。

在单独的线程中运行任务

要在另一个线程中运行函数,请使用 `QtConcurrent::QTaskBuilder::spawn`:

QtConcurrent::task([]{ qDebug("Hello, world!"); }).spawn();

这将在从默认的QThreadPool 获取的独立线程中运行一个lambda函数。

向任务传递参数

若要带参数调用函数,需将参数传递给 `QtConcurrent::QTaskBuilder::withArguments`:

auto task = [](const QString &s){ qDebug() << ("Hello, " + s); };
QtConcurrent::task(std::move(task))
    .withArguments("world!")
    .spawn();

在调用QtConcurrent::QTaskBuilder::withArguments 的时刻,会为每个参数创建一份副本,并在线程开始执行任务时将这些值传递给该线程。在调用QtConcurrent::QTaskBuilder::withArguments 之后对参数所做的更改,该线程将无法感知。

若要运行一个通过引用接受参数的函数,应使用std::ref/cref辅助函数。这些函数会在传递的参数外创建轻量级包装器:

QString s("Hello, ");
QtConcurrent::task([](QString &s){ s.append("world!"); })
    .withArguments(std::ref(s))
    .spawn();

请确保所有被封装的对象存活时间足够长。如果任务的存活时间超过了由 std::ref/cref 封装的对象,可能会导致未定义行为。

从任务返回值

你可以通过QFuture API 获取任务的结果:

auto future = QtConcurrent::task([]{ return 42; }).spawn();
auto result = future.result(); // result == 42

请注意,QFuture::result() 是一个阻塞调用,它会等待结果可用。若要在线程执行完成且结果可用时收到通知,请使用QFutureWatcher 。

如果您希望将结果传递给另一个异步任务,可以使用QFuture::then() 创建一个依赖任务链。更多详细信息,请参阅QFuture 文档。

其他 API 功能

使用不同类型的可调用对象

严格来说,您可以使用任何满足以下条件的任务和参数类型:

std::is_invocable_v<std::decay_t<Task>, std::decay_t<Args>...>

您可以使用自由函数:

QVariant value(42);
auto result = QtConcurrent::task([](const QVariant &var){return qvariant_cast<int>(var);})
                  .withArguments(value)
                  .spawn()
                  .result(); // result == 42

可以使用成员函数:

QString result("Hello, world!");

QtConcurrent::task(&QString::chop)
    .withArguments(&result, 8)
    .spawn()
    .waitForFinished(); // result == "Hello"

您可以使用带有 operator() 的可调用对象:

auto result = QtConcurrent::task(std::plus<int>())
                  .withArguments(40, 2)
                  .spawn()
                  .result() // result == 42

若要使用现有的可调用对象,需将其复制/移动到 `QtConcurrent::task ` 中,或使用 `std::ref`/`cref` 进行封装:

struct CallableWithState
{
    void operator()(int newState) { state = newState; }

    // ...
};

// ...

CallableWithState object;

QtConcurrent::task(std::ref(object))
   .withArguments(42)
   .spawn()
   .waitForFinished(); // The object's state is set to 42

使用自定义线程池

您可以指定自定义线程池:

QThreadPool pool;
QtConcurrent::task([]{ return 42; }).onThreadPool(pool).spawn();

为任务设置优先级

您可以为任务设置优先级:

QtConcurrent::task([]{ return 42; }).withPriority(10).spawn();

如果您不需要未来对象,可以调用QtConcurrent::QTaskBuilder::spawn (QtConcurrent::FutureResult::Ignore ):

QtConcurrent::task([]{ qDebug("Hello, world!"); }).spawn(FutureResult::Ignore);

您可以在函数内部定义一个额外参数(类型为QPromise<T> & ),以此访问与该任务关联的 Promise 对象。该额外参数必须作为传递给函数的第一个参数,且与“使用 Promise 并行运行”模式一样,该函数应返回 void 类型。结果报告通过QPromise API 完成:

void increment(QPromise<int> &promise, int i)
{
    promise.addResult(i + 1);
}

int result = QtConcurrent::task(&increment).withArguments(10).spawn().result(); // result == 11

© 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.