QThread 与QObject::moveToThread利用Qt事件循环在子线程执行多个函数
1. QThread的两种用法
第一种用法就是继承QThread,然后覆写 virtual void run(), 这种用法的缺点是不能利用信号槽机制。
第二种用法就是创建一个线程,创建一个对象,再将对象moveToThread, 这种可以充分利用信号槽机制,与UI框架完美融合。这与std::thread也是不一样的地方。
2. moveToThread用法讲解
示例地址:MultiThread/QThreadDemo · 沁明/QtDemo - 码云 - 开源中国 (gitee.com)
直接调用 QObject::moveToThread() 函数,将继承自 QObject 的对象移到线程里面。此时该对象的 槽函数运行在另一个线程里面。 也就是说,当有信号绑定到该对象的槽函数的时候,并发送信号,该槽函数就运行在另一个线程里,否则该函数仍然运行在对象所在的线程中。
1)先创建一个QObject的子类。
它要运行的函数都可以在子线程中运行。
worker.h
#ifndef WORKER_H
#define WORKER_H#include <QObject>class Worker : public QObject
{Q_OBJECT
public:explicit Worker(QObject *parent = nullptr);public slots:void workSlot();void msg1Slot(const QString &m1);void msg3Slot(const QString &m3);signals:void msg1(const QString &m1);void msg2(const QString &m2);
};#endif // WORKER_H
 
worker.cpp
#include "worker.h"#include <QDebug>
#include <QThread>Worker::Worker(QObject *parent) : QObject{parent} {connect(this, &Worker::msg1, this, &Worker::msg1Slot);
}void Worker::workSlot() {qDebug() << "QThread begin";qDebug() << "child thread id" << QThread::currentThreadId();qDebug() << "QThread end";// 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过// quit() 退出线程exec()。
}void Worker::msg1Slot(const QString &m1) {qDebug() << QThread::currentThreadId() << "receive msg1 " << m1;
}void Worker::msg3Slot(const QString &m3) {qDebug() << QThread::currentThreadId() << "receive msg3 " << m3;
}
 
2)创建worker对象
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), thread(nullptr) {ui->setupUi(this);worker = new Worker;qDebug() << "主线程" << QThread::currentThreadId();connect(worker, &Worker::msg2, this, &MainWindow::msg2Slot);connect(this, &MainWindow::msg3, worker, &Worker::msg3Slot);
} 
直接在窗口构造函数中创建worker对象,程序运行期间这个对象不会被析构。
由于要使用moveToThread函数,所以worker不能设置父对象的,必须为空。
绑定了两个槽函数,分别用来响应消息2和消息3, 但是消息2的槽在窗口对象上,消息3的槽函数在worker对象上。
3)如果不创建子线程,看看3条消息的执行线程在哪?
 如果没有启用子线程的时候,3条消息执行函数都在主线程上。
4)启用子线程之后,3条消息的执行线程是什么?
void MainWindow::on_pushButtonStart_clicked() {qDebug() << "on_pushButtonStart_clicked线程" << QThread::currentThreadId();if (thread)return;thread = new QThread;worker->moveToThread(thread);QObject::connect(thread, &QThread::started, worker, &Worker::workSlot);QObject::connect(thread, &QThread::finished, this,&MainWindow::workerDetach);thread->start();
} 
这里创建了子线程,然后将worker对象移动线程内执行。
workSlot()执行完毕之后其实线程并没有结束,它会执行exec()进入线程的消息循环。
void Worker::workSlot() {qDebug() << "QThread begin";qDebug() << "child thread id" << QThread::currentThreadId();qDebug() << "QThread end";// 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过// quit() 退出线程exec()。
} 
后面在worker上的信号或者槽绑定的触发都会进行响应。

使用QThread启动子线程之后,消息1和消息3 的槽函数在子线程上执行了。
但是消息2的槽函数仍在主线程上。
重新复习一下信号槽绑定
Worker::Worker(QObject *parent) : QObject{parent} {connect(this, &Worker::msg1, this, &Worker::msg1Slot);
} 
 
  connect(worker, &Worker::msg2, this, &MainWindow::msg2Slot);connect(this, &MainWindow::msg3, worker, &Worker::msg3Slot); 
可以看出槽函数的执行线程就是对象所在的线程。
在创建了子线程之后,worker的执行线程已经发生了变化,所以消息1、3执行线程也变成了子线程。
5)停止子线程之后,恢复原来线程
QObject::connect(thread, &QThread::finished, this,&MainWindow::workerDetach);void MainWindow::workerDetach() {qDebug() << "workerDetach线程" << QThread::currentThreadId();worker->moveToThread(QThread::currentThread());
} 
设置在线程退出之后重新移动对象到主线程。

相关文章:
QThread 与QObject::moveToThread利用Qt事件循环在子线程执行多个函数
1. QThread的两种用法 第一种用法就是继承QThread,然后覆写 virtual void run(), 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程,创建一个对象,再将对象moveToThread, 这种可以充分利用信号槽机制ÿ…...
6-2 归并排序
6-2 归并排序 分数 10 全屏浏览 切换布局 作者 软件工程DS&A课程组 单位 燕山大学 以下代码采用分而治之算法实现归并排序。请补充函数mergesort()的代码。提示:mergesort()函数可用递归实现,其中参…...
Java NIO(一) 概述
NIO主要用于以少量线程来管理多个网络连接,处理其上的读写等事件。在大量连接情况下,不管是效率还是空间占用都要优于传统的BIO。 Java NIO 由以下几个核心部分组成: Channel Buffer Selector Selector 如果你的应用打开了多个连接&#x…...
JUC线程池最佳实践
参考:Java 线程池最佳实践 | JavaGuide 使用构造函数创建线程池。【使用有界队列,控制线程创建数量】 SpringBoot 中的 Actuator 组件 / ThreadPoolExecutor 的相关 API监控线程池运行状态 是不同的业务使用不同的线程池【父子任务用同一个线程池容易死…...
2024最新版Node.js下载安装及环境配置教程(非常详细)
一、进入官网地址下载安装包 官网:Node.js — Run JavaScript Everywhere 其他版本下载:Node.js — Download Node.js (nodejs.org) 选择对应你系统的Node.js版本 二、安装程序 (1)下载完成后,双击安装包…...
计算机网络5:运输层
概述 进程间基于网络的通信 计算机网络中实际进行通信的真正实体,是位于通信两端主机中的进程。 如何为运行在不同主机上的应用进程提供直接的逻辑通信服务,就是运输层的主要任务。运输层协议又称为端到端协议。 运输层向应用层实体屏蔽了下面网络核心…...
昂科烧录器支持HangShun航顺芯片的32位微控制器HK32F030C8T6
芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表,其中HangShun航顺芯片的32位微控制器HK32F030C8T6已经被昂科的通用烧录平台AP8000所支持。 HK32F030C8T6使用ARM Cortex-M0内核,最高工作频率96 MHz,内置最…...
纯css星空动画
让大家实现一个这样的星空动画效果,大家会怎么做? js,不! 其实使用css就能写 我也不藏着掖着,源码直接放下面了 <script setup></script><template><div class"box"><div v-for"i in 5" :key"i" :class"layer…...
使用Apache Flink实现实时数据同步与清洗:MySQL和Oracle到目标MySQL的ETL流程
使用Apache Flink实现实时数据同步与清洗:MySQL和Oracle到目标MySQL的ETL流程 实现数据同步的ETL(抽取、转换、加载)过程通常涉及从源系统(如数据库、消息队列或文件)中抽取数据,进行必要的转换࿰…...
postman教程-22-Newman结合Jenkins执行自动化测试
上一小节我们学习了Postman Newman运行集合生成测试报告的方法,本小节我们讲解一下Postman Newman结合Jenkins执行自动化测试的方法。 在软件开发过程中,持续集成(CI)是一种实践,旨在通过自动化的测试和构建过程来频繁…...
uniapp实现tabBar功能常见的方法
在 UniApp 中实现 Tab 功能通常涉及到使用 <navigator> 组件结合 tabBar 配置,或者通过自定义的视图切换逻辑来实现。以下是两种常见的实现方式: 1. 使用 tabBar 配置 UniApp 支持在 pages.json 文件中配置 tabBar,以在应用的底部或顶…...
智慧在线医疗在线诊疗APP患者端+医生端音视频诊疗并开处方
智慧在线医疗:音视频诊疗新纪元 🌐 智慧医疗新篇章 随着科技的飞速发展,智慧医疗正逐步走进我们的生活。特别是在线医疗,凭借其便捷、高效的特点,已成为许多患者的首选。而其中的“智慧在线医疗患者端医生端音视频诊疗…...
攻防平台搭建与简易渗透工具箱编写
知识点:攻防平台搭建,虚拟机的网络模式详解,安全脚本编写 虚拟机的网络模式: 虚拟机(VM)的网络模式决定了虚拟机与宿主机以及外部网络之间的连接方式。不同的虚拟化平台(如VMware, VirtualBox,…...
SQL EXISTS 关键字的使用与理解
SQL EXISTS 关键字的使用与理解 SQL(Structured Query Language)是一种用于管理关系数据库管理系统(RDBMS)的标准编程语言。在SQL中,EXISTS关键字是一个逻辑运算符,用于检查子查询中是否存在至少一行数据。…...
开源低代码平台,JeecgBoot v3.7.0 里程碑版本发布
项目介绍 JeecgBoot是一款企业级的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue3,Mybatis-plus,Shiro,JWT 支持微服务。强大的代码生成器让前后端代码一键生成! JeecgBoot引领…...
名侦探李先生第一话:谁是真正的凶手(只出现一次的数字相关题解(力扣)+位操作符回忆)
引子:我们在之前的案子中破解过基础的单身狗问题,那面对更有挑战的案子,且看李先生如何破局,那下凶手! 复习: 1,位操作符: 正整数原,反,补码都相同 首位是…...
【PA交易】BackTrader(一): 如何使用实时tick数据和蜡烛图
背景和需求 整合Tick数据是PA交易的回测与实盘基本需求。多数交易回测框架往往缺乏对大规模Tick数据直接而全面的支持。Tick数据因其体量庞大(例如,某棕榈油主力合约四年间的数据达8GB)为结合价格趋势与PA分析带来挑战,凸显了实时…...
HTML(16)——边距问题
清楚默认样式 很多标签都有默认的样式,往往我们不需要这些样式,就需要清楚默认样式 写法: 用通配符选择器,选择所有标签,清除所有内外边距选中所有的选择器清楚 *{ margin:0; padding:0; } 盒子模型——元素溢出 作…...
【Godot4自学手册】第四十二节实现拖拽进行物品交换和数量叠加
这一节我们主要学习背包系统中的物品拖拽后,物品放到新的位置,或交换物品位置,如果两个物品属于同一物品则数量相加。具体效果如下: 一、修改item.tscn场景 给item.tscn场景的根节点Item添加Label子节点,命名为Numv…...
存储系统概述
目录 层次结构 存储器的分类 存储器的编址和端模式 存储器端模式 存储器的技术指标 1. 存储容量 示例: 2. 访问速度 访问速度的表现形式: 示例: 3. 功耗 示例: 4. 可靠性 可靠性指标: 示例:…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...
EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...
