QtConcurrent入门
QtConcurrent 是 Qt 提供的一个高级并发编程框架,它简化了并行算法的实现,让开发者能够更容易地利用多核处理器的优势。
1. QtConcurrent 基础
基本概念
QtConcurrent 提供了几种并行编程模式:
-
并行映射:对容器中的每个元素应用函数
-
并行过滤:基于条件筛选容器元素
-
并行归约:将容器元素合并为单个结果
-
并行运行:简单地在后台运行函数
准备工作
使用 QtConcurrent 前需要:
#include <QtConcurrent>
并在项目文件(.pro)中添加:
QT += concurrent
2. 基本用法
并行运行函数 (run)
最简单的用法是在另一个线程中运行函数:
// 定义一个普通函数
int computeSomething(int x) {return x * x;
}// 在后台线程中运行
QFuture<int> future = QtConcurrent::run(computeSomething, 10);// 获取结果(会阻塞直到结果可用)
int result = future.result();
也可以使用 lambda 表达式:
QFuture<int> future = QtConcurrent::run([](int x) {return x * x;
}, 10);
并行映射 (map)
对容器中的每个元素应用函数:
QList<int> list = {1, 2, 3, 4, 5};// 原地修改每个元素
QtConcurrent::map(list, [](int &x) {x *= 2;
});// list 现在是 {2, 4, 6, 8, 10}
并行映射并返回新容器 (mapped)
QList<int> list = {1, 2, 3, 4, 5};QFuture<QList<int>> future = QtConcurrent::mapped(list, [](int x) {return x * 2;
});QList<int> result = future.result();
// result 是 {2, 4, 6, 8, 10}
并行过滤 (filter)
QList<int> list = {1, 2, 3, 4, 5};// 原地过滤
QtConcurrent::filter(list, [](int x) {return x % 2 == 0; // 只保留偶数
});// list 现在是 {2, 4}
并行过滤并返回新容器 (filtered)
QList<int> list = {1, 2, 3, 4, 5};QFuture<QList<int>> future = QtConcurrent::filtered(list, [](int x) {return x % 2 == 0;
});QList<int> result = future.result();
// result 是 {2, 4}
并行归约 (reduce)
将容器元素合并为单个结果:
QList<int> list = {1, 2, 3, 4, 5};int sum = QtConcurrent::blockingReduced(list, [](int &result, int x) {result += x;
});// sum = 15
3. 监控异步操作
使用 QFutureWatcher 监控异步操作进度和结果:
QFutureWatcher<int> *watcher = new QFutureWatcher<int>();// 连接信号
connect(watcher, &QFutureWatcher<int>::finished, []() {qDebug() << "计算完成";
});connect(watcher, &QFutureWatcher<int>::progressValueChanged, [](int progress) {qDebug() << "进度:" << progress;
});// 启动异步计算
QFuture<int> future = QtConcurrent::run([]() {int result = 0;for (int i = 0; i < 100; ++i) {QThread::msleep(50); // 模拟耗时操作result += i;}return result;
});watcher->setFuture(future);
4. 高级特性
取消操作
QFuture<void> future = QtConcurrent::run([]() {while (!QThread::currentThread()->isInterruptionRequested()) {// 执行工作}
});// 取消操作
future.cancel();
设置线程池
QThreadPool::globalInstance()->setMaxThreadCount(4); // 设置最大线程数QtConcurrent::run(QThreadPool::globalInstance(), []() {// 使用全局线程池
});
链式操作
QList<int> list = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};QFuture<int> future = QtConcurrent::mapped(list, [](int x) {return x * x; // 平方}).filtered([](int x) {return x % 2 == 0; // 只保留偶数}).reduced([](int &result, int x) {result += x; // 求和});int result = future.result();
5. 注意事项
-
线程安全:确保被调用的函数是线程安全的
-
GUI操作:不能在非主线程中直接操作GUI组件
-
异常处理:QtConcurrent 中抛出的异常需要通过 QFuture 捕获
-
性能考虑:对于非常小的任务,线程创建的开销可能超过并行化的收益
6. 简单示例
下面是一个完整的示例,演示如何使用 QtConcurrent 处理图像:
#include <QCoreApplication>
#include <QtConcurrent>
#include <QDebug>
#include <QImage>// 图像处理函数
QImage processImage(const QImage &image) {QImage result = image;for (int y = 0; y < result.height(); ++y) {for (int x = 0; x < result.width(); ++x) {QColor color = result.pixelColor(x, y);color.setRed(255 - color.red()); // 反色color.setGreen(255 - color.green());color.setBlue(255 - color.blue());result.setPixelColor(x, y, color);}}return result;
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 加载图像列表QList<QImage> images = {QImage("image1.png"), QImage("image2.png")};// 并行处理图像QFuture<QImage> future = QtConcurrent::mapped(images, processImage);// 监控进度QFutureWatcher<QImage> watcher;watcher.setFuture(future);QObject::connect(&watcher, &QFutureWatcher<QImage>::progressValueChanged,[](int progress) {qDebug() << "处理进度:" << progress;});QObject::connect(&watcher, &QFutureWatcher<QImage>::finished, [&]() {qDebug() << "所有图像处理完成";a.quit();});return a.exec();
}