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

Qt 多线程编程: moveToThread 模式讲解

目录

Qt 多线程编程: moveToThread 模式

核心理念

旧做法:继承 QThread

推荐:moveToThread

实现步骤图解

1. 定义 Worker

2. 实例化 QThread

3. 移动对象

4. 连接与启动

最佳实践与常见陷阱


Qt 多线程编程: moveToThread 模式

这是 Qt 官方推荐的 "Worker-Object" 多线程实现方式。告别错误的QThread继承法,掌握真正的事件驱动多线程模型。

核心理念

为什么选择 Worker-Object 模式?

很多人误以为QThread本身就是线程。其实,QThread只是线程的管理者。

旧做法:继承 QThread

直接重写run()函数。这种做法使得只有 run 函数内部的代码在子线程运行,而类中的槽函数(Slot)依然在主线程运行,极易导致线程安全问题。

推荐:moveToThread

创建一个继承自QObject的 Worker 类,实例化后使用obj->moveToThread(thread)移动它。这样该对象的所有槽函数都会自动在子线程中执行。

实现步骤图解

1. 定义 Worker

创建一个继承 QObject 的类,把耗时任务写在槽函数里。

2. 实例化 QThread

创建一个普通的 QThread 对象,不需要继承它。

3. 移动对象

调用worker->moveToThread(thread)

4. 连接与启动

连接信号槽,然后调用thread->start()

最佳实践与常见陷阱

陷阱:在 Worker 的构造函数中创建对象

千万不要这样做。如果在 Worker 构造函数里new QTimer或其他 QObject,这些子对象会属于创建 Worker 的线程(通常是主线程)。当你调用moveToThread时,虽然 Worker 移动了,但它的子对象可能不会正确移动(如果它们已经设置了父子关系,会一起移动;但如果没有父子关系,就会留在主线程)。

最佳实践:在 Worker 的start()init()槽函数中分配资源,该槽函数在线程启动后通过信号触发执行。

内存管理:如何优雅退出?

线程结束后需要清理QThread对象和Worker对象。推荐的连接方式是:

  • connect(worker, &Worker::finished, thread, &QThread::quit); // 工人干完活,告诉线程退出循环
  • connect(worker, &Worker::finished, worker, &Worker::deleteLater); // 工人干完活,销毁自己
  • connect(thread, &QThread::finished, thread, &QThread::deleteLater); // 线程退出后,销毁线程对象

QtConcurrent vs QThreadexpand_more

并不是所有多线程都需要moveToThread

  • QtConcurrent::run:适合 "用完即走" 的一次性计算任务,不需要事件循环,不需要长期驻留。
  • moveToThread:适合需要长期运行、处理多个信号、需要事件循环(Event Loop)的服务型任务(如串口通信、TCP服务器、硬件轮询)。

注意点:

  • quit()只是请求线程事件循环退出;

  • wait()阻塞等到线程真的结束

  • 如果wait()返回了(没超时、没卡住),那说明线程已经结束了,QThread::finished一定已经在结束过程中发出过

  • 但这个if代码块“执行结束”并不等于一定会结束:如果线程里有阻塞/死循环,wait()可能一直卡住,代码块就不会结束,也谈不上发finished

http://www.rkmt.cn/news/89387.html

相关文章:

  • 网站域名:关键的战略资产
  • n8n第十节 把Markdown格式的会议纪要发到企微
  • 【图像加密】基于matlab超混沌序列和DNA序列图像加密【含Matlab源码 14689期】
  • LC项目实战一:PCB设计(三)
  • 《Effective Java》第24条:静态成员类优于非静态成员类
  • Web Services 总结
  • 【题解】Luogu P10502 Matrix Power Series
  • SpringBoot 企业级接口加密【通用、可配置、解耦的组件】「开闭原则+模板方法+拦截器/中间件模式」
  • 【题解】Luogu P5175 数列
  • 论文AI率90%→5%!DeepSeek四大降ai率指令+3款神器实测(保姆级教程)
  • 05_C 语言进阶之避坑指南:编译器优化等级 —— 嵌入式开发中被忽略的 “隐形陷阱”
  • 【笔记】ST 表
  • Flutter Bloc 状态管理深度解析与开源鸿蒙 ArkUI 对标分析
  • 【笔记】龟速乘与快速幂
  • 2025 最新家电维修平台 TOP5 评测!优质家电维修服务商榜单发布,数智化赋能 + 全城覆盖,品质服务重构家庭生活体验 - 全局中转站
  • GitLab与DeepSeek协同实现MR自动评审实践指南
  • CF 口胡记录
  • 2025最新家电维修/家电安装/租房/家政保洁/找房服务推荐——速达优家(微信小程序),一站式解决居家难题,优选平台实力护航 - 全局中转站
  • 基于springboot的档案数字化管理系统
  • B样条曲线根据曲率极值进行分段速度规划的方法介绍
  • 【笔记】最近公共祖先 Tarjan 算法
  • Spring的DI依赖注入(配置文件方式)
  • Office Tool Plus v10.29.50 office安装激活一条龙
  • 如何编写优美的代码:从工匠到艺术家的修炼之路
  • AI搜索焦虑自救指南:一份面向2026年的系统化追赶方案
  • 告别文件整理拖延症!快速找关键字 TXT + 批量复制到目标文件夹,躺平搞定
  • 《追问者宪章》完整版
  • 视频剪辑软件电脑版排行榜,2025年度前十名软件推荐
  • Error occurred during initialization of VMCould not reserve enough space for object heap
  • 东芝与Quantum Corridor实现量子安全网络通信重大突破