并发任务

QtConcurrent::task 提供了在独立线程中运行任务的替代接口。函数的返回值通过 API 提供。QFuture

如果您只想在独立线程中运行一个函数,而不想调整任何参数,请使用QtConcurrent::run ,因为这样可以减少代码的编写。QtConcurrent::task 专为需要执行额外配置步骤的情况而设计。

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

流畅接口

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

您只需设置所需的参数,然后启动任务即可。为了最终完成任务配置,您必须调用QtConcurrent::QTaskBuilder::spawn 。该函数是非阻塞的(即立即返回一个 future 对象),但并不能保证任务立即启动。您可以使用QFutureQFutureWatcher 类监控任务的状态。

请参阅下面的更多示例和解释。

在单独的线程中运行任务

要在另一个线程中运行一个函数,请使用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"

可以使用带操作符()的可调用对象:

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 对象。该附加参数必须是传递给函数的第一个参数,并且与 "使用承诺并发运行 "模式一样,函数应返回 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

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