news 2026/7/1 12:59:02

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 15:47:54

Pandas DataFrame:数据处理的强大工具

Pandas DataFrame:数据处理的强大工具 引言 在数据分析领域,Pandas DataFrame 是一个不可或缺的工具。它是 Python 中一个强大的数据分析库,能够帮助我们高效地处理和分析数据。本文将详细介绍 Pandas DataFrame 的概念、特点、使用方法以及在实际应用中的优势。 什么是 …

作者头像 李华
网站建设 2026/6/30 4:37:06

XML 语法详解

XML 语法详解 引言 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言。它广泛应用于网络数据的传输、数据存储和配置文件等领域。本文将详细介绍XML的语法规则,帮助读者更好地理解和应用XML。 XML基本概念 1. XML文档结构 一个XML文档通常由以下几部分组成: 声…

作者头像 李华
网站建设 2026/6/25 15:53:38

Maven 快照(SNAPSHOT)

Maven 快照(SNAPSHOT) 引言 Maven 快照(SNAPSHOT)是 Maven 中的一个重要概念,它主要用于管理项目依赖的版本。在软件开发过程中,快照版本通常用于表示开发中的不稳定版本,以便开发者可以及时获取到最新的代码变更。本文将详细介绍 Maven 快照的概念、使用方法以及注意…

作者头像 李华
网站建设 2026/6/29 15:13:40

我只是给Typescript提个 typo PR,为什么还要签协议?

第一次给大公司的开源项目(Typescript)提 PR,提交完 GitHub 就弹出一条评论,让你签什么 CLA:microsoft-github-policy-service agree 什么玩意儿?我就改了个拼写错误,还要签协议?CLA…

作者头像 李华
网站建设 2026/6/25 22:04:58

儿童青少年近视该如何科学防控家长是青少年近视防控的“守门人”

儿童青少年近视率的持续攀升,已成为影响国民健康的重要问题。近视不仅会给孩子的学习生活带来不便,还可能随着年龄增长发展为高度近视,引发眼底病变等潜在风险。在近视防控的全过程中,家长作为孩子成长的第一责任人,肩…

作者头像 李华