Qt QtConcurrent使用入门浅解
QtConcurrent 是 Qt 提供的高级并发编程框架,旨在简化多线程开发——无需手动管理线程生命周期,通过封装线程池(QThreadPool
)和高阶函数(如 map
/filter
/reduce
),快速实现异步任务、容器处理和结果监控。
一、为什么选择 QtConcurrent?
相比底层线程(QThread
/pthread
),QtConcurrent 的优势:
-
自动线程管理:基于全局/自定义线程池,避免频繁创建/销毁线程的开销;
-
高阶抽象:通过
QtConcurrent::run
/map
/filter
等函数,直接处理任务逻辑,无需关心线程调度; -
结果与进度监控:通过
QFuture
和QFutureWatcher
轻松获取异步结果、监听进度和取消任务; -
线程安全简化:内置对共享资源的保护(需配合锁机制)。
二、核心组件
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 提供了一系列模板函数,直接处理任务逻辑:
函数 | 功能 | 示例 |
---|---|---|
| 运行一个函数,返回 |
|
| 对容器每个元素应用函数 |
|
| 过滤容器中满足条件的元素 |
|
| 合并容器元素(类似 MapReduce 的 Reduce) |
|
三、基础用法详解
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 线程。
实现步骤:
-
定义缩放函数:处理单帧图像;
-
用
map
并行处理帧列表; -
监控进度,实时更新 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,提升用户体验。
六、注意事项
-
线程安全:函数内部访问共享资源(如全局变量、硬件寄存器)时,需用
QMutex
加锁; -
异常处理:函数抛出的异常会被捕获并存储在
QFuture
中,调用result()
时需try-catch
; -
取消任务:长时间任务需定期检查
isCanceled()
,避免无效计算; -
内存管理:
QFutureWatcher
需手动释放(deleteLater()
),避免内存泄漏; -
性能优化:根据任务类型调整线程池大小(如计算密集型任务设为核心数,IO 密集型可适当增大)。
总结
QtConcurrent 是 Qt 并发编程的“瑞士军刀”,通过高阶函数和简洁的 API,快速实现异步任务、容器处理和结果监控。在 ZynqMP 等嵌入式平台中,合理使用 QtConcurrent 可充分发挥多核 CPU 性能,提升应用的响应性和实时性。
如需深入,可参考 Qt 官方文档:Qt Concurrent Module。
惠州大亚湾