Qt 之 QtConcurrent

本文深入解析QtConcurrent::run()函数,演示如何在Qt中利用此函数将任务分配到不同线程,实现多线程编程。通过具体代码示例,展示了普通函数和成员函数在独立线程中的调用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文以 Qt 中的 QtConcurrent::run() 函数为例,介绍如何将函数运行在单独的某一个线程中。

1  QtConcurrent::run()

  QtConcurrent 是一个命名空间,它提供了高层次的函数接口 (APIs),使得编写的程序,可根据当前计算机中实际的 CPU 核数,自动调整运行的线程数目。

  下面是 Qt 中的自带例程 runfunction,对应于安装目录为  D:\Qt\Qt5.8.0\Examples\Qt-5.8\qtconcurrent\runfucntion

1.1  .pro 工程文件

  使用 QtConcurrent 模块,需要在 .pro 中添加: QT += concurrent

QT += concurrent widgets
CONFIG += console
CONFIG -= app_bundle

SOURCES += main.cpp

1.2  main.cp

#include <QApplication>
#include <QDebug>
#include <QThread>

#include <QString>
#include <QtConcurrent>

void func(QString name)
{
    qDebug() << "Hello" << name << "from" << QThread::currentThread();
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QFuture<void> fut1 = QtConcurrent::run(func, QString("Thread 1"));
    QFuture<void> fut2 = QtConcurrent::run(func, QString("Thread 2"));

    fut1.waitForFinished();
    fut2.waitForFinished();
}

 

 

可以看到,使用 QtConcurrent::run() 函数,分别将  func() 运行在两个不同的线程之中,输出的结果如下:

Hello "Thread 2" from QThread(0x3597f0, name = "Thread (pooled)")
Hello "Thread 1" from QThread(0x337720, name = "Thread (pooled)")

 

  下面是对使用 QtConcurrent::run() 的详细阐释,阅读完 2 和 3,再来看上面的 runfunction 例程,就非常容易理解了。

 2  普通函数

2.1  将函数运行在某一个线程中

extern void func();
QFuture<void> future = QtConcurrent::run(func);

  如果要为其指定线程池,可以将线程池的指针作为第一个参数传递进去

extern void func();
QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, func);

2.2  向该函数传递参数

  需要传递的参数,需要跟在函数名之后,依次加入

extern void FuncWithArguments(int arg1, const QString &string);

 int integer = ...;
 QString string = ...;

 QFuture<void> future = QtConcurrent::run(FuncWithArguments,integer,string);

2.3  获取该函数的计算结果

 

extern QString Func(const QByteArray &input);

QByteArray byte_array = ...;

QFuture<QString> future = QtConcurrent::run(func, byte_array);
...
QString result = future.result();

 

3  成员函数

  要将类中的成员函数运行在某一个线程中,可将指向该类实例的 引用或指针 作为 QtConcurrent::run 的第一个参数传递进去,

  常量成员函数一般传递 常量引用 (const reference),而非常量成员函数一般传递 指针 (pointer)

3.1  常量成员函数

   在一个单独的线程中,调用 QByteArray 的常量成员函数 split(),传递给 run() 函数的参数是 bytearray

  QByteArray bytearray = "hello world";
  QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
  ...
  QList<QByteArray> result = future.result();

3.2  非常量成员函数

   在一个单独的线程中,调用 QImage 的非常量成员函数 invertPixels(),传递给 run() 函数的参数是 &image

  QImage image = ...;
  QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba);
  ...
  future.waitForFinished();
  // At this point, the pixels in 'image' have been inverted

 

参考资料:

  Qt 助手 | Qt 5.8 | Qt Concurrent | Concurrent Run

转自:https://www.cnblogs.com/xinxue/p/6840315.html

<think>好的,我现在要解决用户关于QtQtConcurrent::run和QFutureInterface的使用方法及示例的问题。首先,我需要回忆一下自己对这两个类的理解。 用户提到的QtConcurrent::run是Qt并发模块中的一个函数,用于在后台线程中运行函数,并返回一个QFuture对象,以便跟踪异步操作的状态和结果。QFutureInterface看起来像是QFuture的内部实现接口,可能用于手动控制QFuture的状态,比如报告进度、完成情况等。不过,我之前主要使用QtConcurrent::run和QFutureWatcher,对QFutureInterface的具体用法不太熟悉,可能需要查资料。 接下来,我需要参考用户提供的引用内容。引用[2]中有一个QtConcurrent::run的示例代码,展示了如何运行一个函数并传递参数。引用[1]和[4]提到QFuture和QFutureWatcher的配合使用,因为QFuture不是QObject的子类,无法直接使用信号槽,所以需要QFutureWatcher来监听事件并发出信号。引用[3]提到随机访问迭代器在Qt Concurrent中的优势,但可能和当前问题关系不大。 用户的问题包括QtConcurrent::run和QFutureInterface的用法,所以需要分两部分解答。先处理QtConcurrent::run,这部分我比较熟悉,可以结合引用中的示例进行说明。然后关于QFutureInterface,根据我的了解,这个类通常是内部使用的,用户一般不直接操作,但某些高级场景可能需要手动创建QFutureInterface实例,比如自定义异步任务。这时候需要实例化QFutureInterface,调用reportStarted,然后报告结果和完成状态。 可能需要确认Qt文档中QFutureInterface的用法,确保正确性。比如,如何设置进度、结果,以及如何结束任务。例如,调用reportResult()来发送结果,reportFinished()来标记完成。同时,通过future()方法获取关联的QFuture对象。 然后,需要给出示例代码。对于QtConcurrent::run,可以展示基本用法和配合QFutureWatcher的示例。对于QFutureInterface,可能需要编写一个手动控制的例子,比如在自定义线程中执行任务,并通过接口报告进度和结果。 另外,注意用户提到的系统级指令,比如数学公式的格式,但这个问题可能不涉及数学公式,所以可能不需要处理这部分。但需要确保代码块正确,使用中文回答,结构清晰,生成相关问题。 现在需要组织回答的结构:先介绍QtConcurrent::run的使用方法,给出示例,然后讲解QFutureInterface的应用场景和示例。最后生成相关问题。 需要确保代码示例正确,比如在QtConcurrent::run中如何传递参数,如何处理返回的QFuture。对于QFutureInterface的例子,需要正确初始化,报告开始、结果、进度,并结束任务。同时,提到注意事项,如线程安全和正确调用接口的顺序。 可能遇到的问题:用户可能混淆QFuture和QFutureInterface的用途,需要明确区分。QFuture是用于获取异步结果的,而QFutureInterface是用于生成和管理这些结果的,通常由框架内部使用,但在需要自定义异步操作时,用户可能需要直接使用它。 总结步骤: 1. 介绍QtConcurrent::run的基本用法,示例代码。 2. 说明如何配合QFutureWatcher监控状态。 3. 解释QFutureInterface的作用,并提供手动创建异步任务的示例。 4. 强调注意事项和常见问题。 5. 生成相关问题。 需要检查引用的内容是否相关,并正确标注引用标记。例如,引用[2]中的示例代码可以用来支持QtConcurrent::run的讲解,引用[1]和[4]说明QFuture和QFutureWatcher的配合使用。 最后,确保回答结构清晰,语言准确,示例代码正确无误,并符合用户给出的格式要求。</think>### QtConcurrent::run 与 QFutureInterface 使用详解 #### 一、QtConcurrent::run 的基本用法 `QtConcurrent::run` 用于在后台线程中执行函数,并返回 `QFuture` 对象以跟踪异步任务状态。 **核心功能**: - 支持普通函数、Lambda、类成员函数 - 自动管理线程池资源 - 通过 `QFuture` 获取结果或监控进度 **示例1:执行普通函数** ```cpp #include <QtConcurrent/QtConcurrentRun> #include <QDebug> void calculateSum(int a, int b) { qDebug() << "Result:" << a + b; } int main() { auto future = QtConcurrent::run(calculateSum, 3, 5); future.waitForFinished(); // 阻塞等待完成 return 0; } ``` **示例2:配合 QFutureWatcher 监控信号** ```cpp QFutureWatcher<void> watcher; connect(&watcher, &QFutureWatcher<void>::finished, [](){ qDebug() << "Task completed!"; }); QFuture<void> future = QtConcurrent::run([](){ // 耗时操作 }); watcher.setFuture(future); // 绑定监控对象 ``` #### 二、QFutureInterface 高级控制 `QFutureInterface` 是 `QFuture` 的底层接口,用于手动控制异步任务状态,适用于**自定义异步操作**的场景[^4]。 **典型流程**: 1. 创建接口对象并初始化状态 2. 报告任务开始 3. 发送进度/结果 4. 标记任务完成 **示例:手动实现异步计算** ```cpp #include <QFutureInterface> #include <QThread> class CustomTask : public QRunnable { public: QFuture<int> start() { QFutureInterface<int> interface; interface.reportStarted(); // 状态标记为运行中 m_future = interface.future(); QtConcurrent::run([this, interface]() mutable { int result = 0; for (int i=1; i<=5; ++i) { QThread::sleep(1); result += i; interface.setProgressValue(i); // 更新进度 } interface.reportResult(result); // 发送结果 interface.reportFinished(); // 标记完成 }); return m_future; } private: QFuture<int> m_future; }; // 使用示例 CustomTask task; QFutureWatcher<int> watcher; connect(&watcher, &QFutureWatcher<int>::finished, [&](){ qDebug() << "Final result:" << watcher.result(); }); watcher.setFuture(task.start()); ``` #### 三、关键注意事项 1. **线程安全**:`QFutureInterface` 的方法需在**同一线程**调用[^4] 2. **状态顺序**:必须按 `reportStarted()` → 发送结果/进度 → `reportFinished()` 顺序操作 3. **资源释放**:使用 `QRunnable` 时需启用 `setAutoDelete(true)` 避免内存泄漏 4. **进度精度**:随机访问迭代器容器(如 `QVector`)才能提供准确的进度信息[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值