当前位置: 首页 > news >正文

Qt QtConcurrent使用入门浅解

QtConcurrent 是 Qt 提供的​​高级并发编程框架​​,旨在简化多线程开发——无需手动管理线程生命周期,通过封装线程池(QThreadPool)和高阶函数(如 map/filter/reduce),快速实现异步任务、容器处理和结果监控。

一、为什么选择 QtConcurrent?

相比底层线程(QThread/pthread),QtConcurrent 的优势:

  • ​自动线程管理​​:基于全局/自定义线程池,避免频繁创建/销毁线程的开销;

  • ​高阶抽象​​:通过 QtConcurrent::run/map/filter等函数,直接处理任务逻辑,无需关心线程调度;

  • ​结果与进度监控​​:通过 QFutureQFutureWatcher轻松获取异步结果、监听进度和取消任务;

  • ​线程安全简化​​:内置对共享资源的保护(需配合锁机制)。

二、核心组件

QtConcurrent 的核心是 ​QFuture​(异步结果句柄)和 ​QFutureWatcher​(结果监控器),以及命名空间内的高阶函数。

1. QFuture:异步操作的“结果包裹器”

  • 代表一个​​异步操作的结果​​,可通过它获取返回值、进度、取消状态;

  • 常用方法:

    • result():阻塞获取最终结果(需谨慎,避免 UI 卡顿);

    • resultAt(int index):获取容器处理任务中的单个元素结果(如 map后的元素);

    • progress()/progressRange():获取/设置进度范围;

    • isFinished()/isCanceled():判断任务状态;

    • waitForFinished():阻塞等待任务完成。

2. QFutureWatcher:结果的“观察者”

  • 继承自 QObject,通过信号监控 QFuture的状态变化:

    • finished():任务完成;

    • canceled():任务取消;

    • progressChanged(int):进度更新;

    • resultReadyAt(int):容器处理任务中某个元素的结果就绪;

    • resultReady(QVariant):单个结果就绪(部分场景)。

3. 高阶函数(命名空间 QtConcurrent

QtConcurrent 提供了一系列模板函数,直接处理任务逻辑:

函数

功能

示例

QtConcurrent::run

运行一个函数,返回 QFuture

run(myFunction, arg1, arg2)

QtConcurrent::map

对容器​​每个元素​​应用函数

map(list, toUpper)

QtConcurrent::filter

过滤容器中​​满足条件的元素​

filter(list, isEven)

QtConcurrent::reduce

合并容器元素(类似 MapReduce 的 Reduce)

reduce(list, sum)

三、基础用法详解

1. 用 QtConcurrent::run运行耗时函数

​场景​​:后台执行一个不阻塞 UI 的耗时操作(如计算、IO)。

步骤:
  • ​定义耗时函数​​:可返回值,也可通过 QFutureInterface报告进度/取消。

  • ​启动任务​​:用 QtConcurrent::run运行函数,获取 QFuture

  • ​监控任务​​:用 QFutureWatcher监听结果/进度/取消。

​示例代码​​:

#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QDebug>// 耗时函数:模拟计算,支持进度报告和取消
int longRunningTask(int base) 
{QFutureInterface<int> futureInterface;futureInterface.setProgressRange(0, 100); // 进度范围 0~100futureInterface.reportStarted();          // 报告任务开始for (int i = 0; i < 100; ++i) {if (futureInterface.isCanceled()) {   // 检查是否被取消qDebug() << "Task canceled!";return -1;}QThread::msleep(50);                  // 模拟工作futureInterface.setProgress(i);       // 更新进度}futureInterface.reportFinished();         // 报告任务结束return base * 2;                          // 返回结果
}// 在 UI 槽函数中启动任务
void MyWidget::onStartTask() 
{QFuture<int> future = QtConcurrent::run(longRunningTask, 10); // 传递参数 10QFutureWatcher<int>* watcher = new QFutureWatcher<int>(this);// 监听进度变化connect(watcher, &QFutureWatcher<int>::progressChanged, this, [=](int progress) {qDebug() << "Progress:" << progress << "%";ui->progressBar->setValue(progress); // 更新 UI 进度条});// 监听任务完成connect(watcher, &QFutureWatcher<int>::finished, this, [=]() {qDebug() << "Result:" << watcher->result(); // 输出 20watcher->deleteLater(); // 清理资源});watcher->setFuture(future); // 关联 QFuture 和 watcher
}

​关键点​​:

  • 函数内部通过 QFutureInterface报告进度和取消状态;

  • QFutureWatcher监听进度变化,实时更新 UI;

  • 任务取消时,函数通过 isCanceled()退出,避免无效计算。

2. 用 QtConcurrent::map处理容器

​场景​​:对容器(如 QList/QVector)中的每个元素执行相同操作(如字符串转大写、图像缩放)。

示例代码:
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QList>
#include <QString>
#include <QDebug>// 转换函数:字符串转大写
QString toUpper(const QString& str) {return str.toUpper();
}// 启动 map 任务
void MyWidget::onMapStrings() {QList<QString> strings = {"hello", "world", "qt", "concurrent"};QFuture<QString> future = QtConcurrent::map(strings, toUpper); // 对每个元素应用 toUpperQFutureWatcher<QString>* watcher = new QFutureWatcher<QString>(this);// 监听单个元素结果就绪(处理一个元素就触发一次)connect(watcher, &QFutureWatcher<QString>::resultReadyAt, this, [=](int index) {QString result = watcher->resultAt(index); // 获取该元素的结果qDebug() << "Processed index" << index << ":" << result;});// 监听所有元素处理完成connect(watcher, &QFutureWatcher<QString>::finished, this, [=]() {qDebug() << "All results:" << future.results(); // 获取所有结果(QList<QString>)watcher->deleteLater();});watcher->setFuture(future);
}

​关键点​​:

  • map自动将容器元素分发给线程池中的线程处理;

  • resultReadyAt信号在​​每个元素处理完​​时触发,可实时更新 UI;

  • results()返回处理后的完整容器。

3. 用 QtConcurrent::filter过滤容器

​场景​​:从容器中筛选满足条件的元素(如筛选偶数、过滤错误日志)。

示例代码:
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QList>
#include <QDebug>// 谓词函数:判断是否为偶数
bool isEven(int num) {return num % 2 == 0;
}// 启动 filter 任务
void MyWidget::onFilterNumbers() {QList<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};QFuture<int> future = QtConcurrent::filter(numbers, isEven); // 过滤偶数QFutureWatcher<int>* watcher = new QFutureWatcher<int>(this);connect(watcher, &QFutureWatcher<int>::resultReadyAt, this, [=](int index) {qDebug() << "Filtered element:" << watcher->resultAt(index);});connect(watcher, &QFutureWatcher<int>::finished, this, [=]() {qDebug() << "Filtered results:" << future.results(); // 输出 {2,4,6,8,10}watcher->deleteLater();});watcher->setFuture(future);
}

4. 用 QtConcurrent::reduce合并结果

​场景​​:合并容器元素(如求和、求最大值),类似 MapReduce 的 Reduce 阶段。

示例代码:
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QList>
#include <QDebug>// Reduce 函数:两数相加
int sum(int a, int b) {return a + b;
}// 启动 reduce 任务
void MyWidget::onSumNumbers() {QList<int> numbers = {1, 2, 3, 4, 5};QFuture<int> future = QtConcurrent::reduce(numbers, sum); // 计算总和QFutureWatcher<int>* watcher = new QFutureWatcher<int>(this);connect(watcher, &QFutureWatcher<int>::finished, this, [=]() {qDebug() << "Sum:" << watcher->result(); // 输出 15watcher->deleteLater();});watcher->setFuture(future);
}

​关键点​​:

  • reduce将容器分成多个块,每个线程处理一块,再将块结果合并;

  • Reduce 函数需满足​​结合律​​(如加法、乘法),否则结果不确定。

四、线程池配置

QtConcurrent 基于 QThreadPool管理线程,默认使用​​全局线程池​​。可根据硬件资源调整线程数(如 ZynqMP 的 A53 核心数):

#include <QThreadPool>// 获取全局线程池
QThreadPool* globalPool = QThreadPool::globalInstance();
globalPool->setMaxThreadCount(4); // 设置最大线程数为 4(匹配 ZynqMP 的 4 个 A53 核心)
globalPool->setExpiryTimeout(30000); // 线程空闲 30 秒后销毁,避免资源浪费// 使用自定义线程池
QThreadPool* customPool = new QThreadPool(this);
customPool->setMaxThreadCount(2);
QFuture<int> future = QtConcurrent::run(customPool, longRunningTask, 10); // 指定线程池运行任务

五、嵌入式场景实践

以​​视频帧缩放​​为例,展示 QtConcurrent 在嵌入式设备中的应用:

场景需求

从摄像头获取视频帧(QImage),需缩放至 640x480 显示,要求不阻塞 UI 线程。

实现步骤:

  1. ​定义缩放函数​​:处理单帧图像;

  2. ​用 map并行处理帧列表​​;

  3. ​监控进度,实时更新 UI​​。

代码实现:
// 缩放函数:将帧缩放到指定尺寸
QImage scaleFrame(const QImage& frame, const QSize& targetSize) {if (frame.isNull()) return QImage();return frame.scaled(targetSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}// 视频处理槽函数:接收原始帧列表
void VideoProcessor::processFrameBatch(const QList<QImage>& rawFrames) {// 目标尺寸:适配监视器 UIQSize targetSize(640, 480);// 启动 map 任务:并行缩放所有帧QFuture<QImage> future = QtConcurrent::map(rawFrames, [=](const QImage& frame) {return scaleFrame(frame, targetSize);});// 创建 watcher 监控任务QFutureWatcher<QImage>* watcher = new QFutureWatcher<QImage>(this);// 单帧结果就绪:更新 UI 中的对应帧connect(watcher, &QFutureWatcher<QImage>::resultReadyAt, this, [=](int index) {QImage scaledFrame = watcher->resultAt(index);emit frameScaled(index, scaledFrame); // 发射信号,UI 组件接收并显示});// 所有帧处理完成:清理资源connect(watcher, &QFutureWatcher<QImage>::finished, this, [=]() {qDebug() << "Batch scaling finished!";watcher->deleteLater();});watcher->setFuture(future);
}

​优势​​:

  • 并行处理多帧,充分利用 ZynqMP 的多核 CPU;

  • 不阻塞 UI 线程,保证监视器实时响应;

  • 单帧结果就绪后立即更新 UI,提升用户体验。

六、注意事项

  1. ​线程安全​​:函数内部访问共享资源(如全局变量、硬件寄存器)时,需用 QMutex加锁;

  2. ​异常处理​​:函数抛出的异常会被捕获并存储在 QFuture中,调用 result()时需 try-catch

  3. ​取消任务​​:长时间任务需定期检查 isCanceled(),避免无效计算;

  4. ​内存管理​​:QFutureWatcher需手动释放(deleteLater()),避免内存泄漏;

  5. ​性能优化​​:根据任务类型调整线程池大小(如计算密集型任务设为核心数,IO 密集型可适当增大)。

总结

QtConcurrent 是 Qt 并发编程的“瑞士军刀”,通过高阶函数和简洁的 API,快速实现异步任务、容器处理和结果监控。在 ZynqMP 等嵌入式平台中,合理使用 QtConcurrent 可充分发挥多核 CPU 性能,提升应用的响应性和实时性。

如需深入,可参考 Qt 官方文档:Qt Concurrent Module。

惠州大亚湾

http://www.dtcms.com/a/460964.html

相关文章:

  • C语言字符串与内存操作函数完全指南
  • 【第五章:计算机视觉-项目实战之生成式算法实战:扩散模型】2.CV黑科技:生成式算法理论-(5)Stable Diffusion模型讲解
  • Cookie和Seeion在客户端和服务端的角色作用
  • Linux 远程Ubuntu服务器本地部署大模型 EmoLLM 中常见的问题及解决方案 万字详解
  • 如何建设公司网站信息灯塔网站seo
  • Java 中 `equals()`、`==` 和 `hashCode()` 的区别
  • 成像系统(十四-1:《工业级ISP流水线:ISP前端处理 - 从原始数据到可用图像》):从LED冬奥会、奥运会及春晚等大屏,到手机小屏,快来挖一挖里面都有什么
  • vue-router(vue 路由)基本使用指南(二)
  • 深入理解 Java中的 异常和泛型(指南十二)
  • 草莓植物(plant)【高精度-->array高级!!!】
  • 3D 图表、堆叠饼图为什么是灾难?
  • Nacos 全解析:从注册中心到配置管理的实战指南
  • 微信小程序开发从零基础到项目发布的全流程实战教程(四)
  • wordpress 全站静态二次开发小程序
  • linux命令--后端项目部署
  • 网页版云手机 梦幻西游手游
  • HTML5 与 HTTPS,页面能力、必要性、常见问题与实战排查
  • 网站检索功能怎么做建设宣传网站的必要性
  • 做网站维护需要懂什么网站建设洽谈问题
  • 17、Linux 文件压缩与解压
  • IDEA编译时报错OOM的解决方案
  • .NET驾驭Word之力:基于规则自动生成及排版Word文档
  • 本地web测试服务器快速域名映射工具
  • 自己搭建远程桌面服务器——私有化部署RustDesk
  • 机器人强化学习原理讲解二:关于机器人重置
  • 目标检测YOLO实战应用案例100讲-相机 ISP(三)
  • 网站无障碍建设标准we建站
  • Linux系统为普通用户设置sudo权限
  • 网络流量分析工具
  • 网站基站的建设网站建设学习哪家专业