
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 提供了一系列模板函数,直接处理任务逻辑:
函数 | 功能 | 示例 |
---|---|---|
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
监听结果/进度/取消。
示例代码:
cpp
#include <QtConcurrent/QtConcurrent>
#include <QFutureWatcher>
#include <QDebug>
// 耗时函数:模拟计算,支持进度报告和取消
int longRunningTask(int base)
{
QFutureInterface<int> futureInterface;
futureInterface.setProgressRange(0, 100); // 进度范围 0~100
futureInterface.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); // 传递参数 10
QFutureWatcher<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(); // 输出 20
watcher->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); // 对每个元素应用 toUpper
QFutureWatcher<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(); // 输出 15
watcher->deleteLater();
});
watcher->setFuture(future);
}
关键点:
-
reduce
将容器分成多个块,每个线程处理一块,再将块结果合并; -
Reduce 函数需满足结合律(如加法、乘法),否则结果不确定。
四、线程池配置
QtConcurrent 基于 QThreadPool
管理线程,默认使用全局线程池。可根据硬件资源调整线程数(如 ZynqMP 的 A53 核心数):
cpp
#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) {
// 目标尺寸:适配监视器 UI
QSize 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。

惠州大亚湾