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

QT之QThread 与 QtConcurrent

在开发中不可避免的会遇到耗时操作、后台计算、异步任务等需求。此时,使用多线程编程便成为解决性能与响应式 UI 的关键手段。而 Qt 提供了两种主流的并发机制:

  • QThread底层线程控制类,功能强大,适合复杂线程模型。

  • QtConcurrent基于线程池的高级接口,简洁易用,适合并发任务调度。

虽然它们都可实现多线程任务,但各自适用的场景、易用性、控制粒度却有很大不同:

一、概览对比

项目QThreadQtConcurrent
所属模块QtCoreQtConcurrent
控制粒度低层级(线程生命周期)高层级(任务并发)
线程管理手动控制(start/exit)自动管理(线程池调度)
使用方式继承/组合/moveToThread()使用 QtConcurrent::run() 启动任务
支持信号槽✅(需要事件循环)❌(任务线程中默认无事件循环)
可取消任务✅(需手动控制)
易用性复杂简单
常见用途长期驻留线程、线程间通信并发处理、异步操作、批量计算

 二、QThread:强控制、适合长期任务

方式一:继承 QThread

class MyThread : public QThread {
protected:void run() override {// 自定义线程逻辑}
};

方式二:组合 QObject + moveToThread

Worker *worker = new Worker;
QThread *thread = new QThread;worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
thread->start();

特点

  • 需要自己控制线程生命周期:start()quit()wait()

  • 适合 UI 与线程交互(信号槽机制)。

  • 可以运行事件循环,处理定时器、socket、事件等。

  • 适合需要持久运行或复杂状态管理的后台任务。

三、QtConcurrent:自动调度,适合短期任务

最常用的方式:QtConcurrent::run()

QtConcurrent::run([](){doHeavyWork();
});

支持绑定返回值和观察器

QFuture<QString> future = QtConcurrent::run([]() {return QString("Hello from thread");
});QFutureWatcher<QString> *watcher = new QFutureWatcher<QString>();
QObject::connect(watcher, &QFutureWatcher<QString>::finished, [=](){qDebug() << "Result:" << future.result();watcher->deleteLater();
});
watcher->setFuture(future);

特点

  • 自动使用 QThreadPool 管理线程;

  • 任务无需手动创建线程或事件循环;

  • 适合“函数级别”的并发调用;

  • 不适合需要线程交互或长期保持任务状态的场景。

四、完整示例

4.1、非阻塞常见使用(推荐)

QFuture<QString> future = QtConcurrent::run([]() {QThread::sleep(2);return QString("任务完成");
});QFutureWatcher<QString>* watcher = new QFutureWatcher<QString>();
QObject::connect(watcher, &QFutureWatcher<QString>::finished, [=]() {QString result = future.result();  // ✅ 此时不会阻塞,因为已经 finishedqDebug() << "结果是:" << result;watcher->deleteLater();
});
watcher->setFuture(future);

 4.2、非阻塞带返回值示例

既可以获取到返回值还可以防止任务重复运行

QFuture<int> future;
QFutureWatcher<int> watcher;void MyWorker::startTask()
{if (future.isRunning())return;future = QtConcurrent::run([]() -> int {QThread::sleep(2);return 42;});connect(&watcher, &QFutureWatcher<int>::finished, this, [=]() {qDebug() << "返回值为:" << future.result();});watcher.setFuture(future);
}

4.3、错误示例——阻塞获取数据

QFuture<QString> future = QtConcurrent::run([]() {QThread::sleep(5); // 模拟耗时任务return QString("Done");
});QString result = future.result(); // ⛔ 阻塞:等待上面的任务执行完毕
  • QtConcurrent::run(...) 会把 lambda 提交给线程池去执行(异步),主线程继续往下执行,执行到 future.result(),但是任务还没跑完,结果还没出来;

  • Qt 的 QFuture::result() 必须返回值,所以当前线程(比如主线程)就 阻塞等待,等线程池中的任务执行完成,把结果返回;

 

方法名是否阻塞说明
future.result()✅ 会阻塞阻塞直到任务完成并返回结果
future.waitForFinished()✅ 会阻塞阻塞直到任务结束
future.isRunning()❌ 不阻塞非阻塞方式判断任务是否仍在运行
future.isFinished()❌ 不阻塞判断是否已完成
future.resultCount()❌ 不阻塞并行结果数量(比如 mapped()
QFutureWatcher::finished() 信号❌ 不阻塞信号通知,推荐 UI 中使用

 

五、建议

  1. 不要滥用 QThread:不推荐直接在主线程中执行 run();也不建议频繁创建/销毁线程。

  2. 短期任务用 QtConcurrent 更自然:能显著减少代码量,提高可读性。

  3. 任务有 UI 回调?用 QFutureWatcher:避免在 QtConcurrent 的线程中直接访问 UI(线程不安全)。

  4. 需要信号槽?考虑 moveToThread 模式:结合事件循环,线程间通信更强大。

  5. 并行计算/算法任务?可用 QtConcurrent::mapped/filter/reduce:实现更复杂的 Map-Reduce 模式。

六、总结

QThread QtConcurrent 都是 Qt 提供的强大多线程工具,但使用方式和适用范围不同。

  • QThread 更加底层、可控,适合复杂线程管理、线程间通信;

  • QtConcurrent 更简洁现代,适合并发计算与短时任务;

场景推荐机制理由
文件/网络下载QThread需要事件循环、信号槽响应、状态控制
图像处理/批量压缩QtConcurrent任务独立、计算密集、无需交互
后台服务守护QThread线程常驻、需要持续响应
数据库查询QtConcurrent一次性任务,避免阻塞 UI
UI 按钮触发异步任务QtConcurrent简洁,方便绑定任务完成回调
多任务调度/线程池复用QtConcurrent自动使用线程池,避免重复造轮子

 

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

相关文章:

  • 【自动化运维神器Ansible】Ansible常用模块之cron模块详解
  • GaussDB as的用法
  • 【GaussDB】内存资源告急:深度诊断一起“memory temporarily unavailable“故障
  • DMETL安装流程及简单使用
  • OpenLayers 入门指南【四】:项目初始化
  • Qt小组件 - 8 图片浏览器
  • MySQL高级配置与优化实战指南
  • 利用 SQL Server 实现字符替换的高效函数
  • 第二十一天(shell练习)
  • IT运维的365天--033 跨交换机部署没有单独供电口的爱快AP到另一个地方去
  • 如何选择适合高并发环境的服务器:性能与稳定性的平衡
  • 短剧小程序系统开发:连接创作者与用户的桥梁
  • Node.js + TypeScript 开发健壮的淘宝商品 API SDK
  • 2025年07月23日秋瑶传媒一面
  • 【学习路线】AI开发工程师成长指南:从机器学习基础到大模型应用
  • 调色总监的“色彩炼金术”:在PS中创建LUT,并应用于Premiere Pro视频
  • TCP/IP 网际层详解
  • RCLAMP2574N.TCT Semtech:超低钳位TVS二极管 0.5pF超低电容+±30kV超强防护
  • 【Blender小技巧】Blender使用多边形建形工具创建多边形模型,挤出面,模型创建修改编辑UV贴图
  • PostgreSQL 与 MySQL 时间类型避坑指南
  • 《Ai智能眼镜的市场定义及用户分析》- 深圳市天趣星空科技有限公司 CEO 王洁
  • Java字符串详解
  • Entity Framework Core (EF Core) 使用ado.net
  • 用latex+vscode+ctex写毕业论文
  • Spring源码解读之 JdbcTemplate源码
  • 【基础篇三】WebSocket:实时通信的革命
  • 基于DeepSeek大模型和STM32的矿井“围压-温度-开采扰动“三位一体智能监测系统设计
  • 排序算法 (Sorting Algorithms)-JS示例
  • 安装及使用vscode
  • Unity教程(二十四)技能系统 投剑技能(中)技能变种实现