QThread 与QObject::moveToThread在UI中的应用

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());
}

设置在线程退出之后重新移动对象到主线程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/355801.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker:Harbor

目录 一、Harbor介绍 二、安装 Harbor 2.1 环境准备 2.2下载 Harbor 3.3 修改配置&#xff08;可选&#xff09; 3.4 启动 Harbor 3.5访问 Harbor 三、使用 Harbor 3.1 管理Harbor 一、Harbor介绍 Docker Harbor 是由 VMware 公司开源的一款企业级的 Docker Registry …

基于JSP技术的个性化影片推荐系统

开头语&#xff1a;你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSPServlet 工具&#xff1a;MyEclipse、Tomcat、MySQL 系统展示 首页 …

kafka的基本模型

kafka官网 线程和线程之间的数据交互 在jvm里不同的线程有自己的栈内存&#xff0c;但彼此之间交互可以在共享的内存中进行&#xff0c;即堆内存&#xff0c;堆内存会将这些消息放到队列中&#xff0c;具体实现jvm见&#xff0c;栈内存各自维护&#xff0c;堆内存大家共享 进…

DLS平台:美联储松绑预期升温,金价飙升至2365美元

摘要 美联储鹰派官员古尔斯比对降息态度有所松动&#xff0c;导致金价一度升至2365美元。市场对美联储未来的货币政策预期有所改变&#xff0c;黄金作为避险资产的吸引力增强。本文将详细分析美联储官员态度变化对金价的影响、当前市场对黄金的预期及其未来走势。 美联储官员态…

Pyqt QCustomPlot 简介、安装与实用代码示例(二)

目录 前言实用代码示例彩色图演示散点像素图演示实时数据演示多轴演示对数轴演示 结语 所有文章除特别声明外&#xff0c;均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nixgnauhcuy’s blog&#xff01; 如需转载&#xff0c;请标明出处&#xff01; 完整代码我已经上传到…

第 402 场 LeetCode 周赛题解

A 构成整天的下标对数目 I 计数&#xff1a;遍历 h o u r s hours hours &#xff0c;记录 h o u r s [ i ] % 24 hours[i]\%24 hours[i]%24 的出现次数 class Solution {public:long long countCompleteDayPairs(vector<int>& hours) {vector<int> cnt(24);…

【小白专用 已验证24.6.18】C# SqlSugar操作MySQL数据库实现增删改查

【小白专用24.6.18】C# SqlSugar&#xff1a;连接数据库实现简单的&#xff0c;增、删、改、查-CSDN博客 SqlSugar .Net ORM 5.X 官网 、文档、教程 - SqlSugar 5x - .NET果糖网 SqlSugar项目创建 通过NuGet包管理器搜索SqlSugar&#xff08;MySql还要安装MySql.Data、Newton…

如何计算 GPT 的 Tokens 数量?

基本介绍 随着人工智能大模型技术的迅速发展&#xff0c;一种创新的计费模式正在逐渐普及&#xff0c;即以“令牌”&#xff08;Token&#xff09;作为衡量使用成本的单位。那么&#xff0c;究竟什么是Token呢&#xff1f; Token 是一种将自然语言文本转化为计算机可以理解的…

【Linux】进程信号2——阻塞信号,捕捉信号

1.阻塞信号 1.1. 信号其他相关常见概念 在开始内容之前&#xff0c;先介绍一些信号的专业名词&#xff1a; 实际执行信号的处理动作称为信号递达&#xff08;Delivery&#xff09;信号从产生到递达之间的状态&#xff0c;称为信号未决&#xff08;Pending&#xff09;&#…

【秋招刷题打卡】Day01-自定义排序

Day01-自定排序 前言 给大家推荐一下咱们的 陪伴打卡小屋 知识星球啦&#xff0c;详细介绍 >笔试刷题陪伴小屋-打卡赢价值丰厚奖励 < ⏰小屋将在每日上午发放打卡题目&#xff0c;包括&#xff1a; 一道该算法的模版题 (主要以力扣&#xff0c;牛客&#xff0c;acwin…

【Git】 -- Part1 -- 基础操作

1. Git简介 Git 是一个开源的分布式版本控制系统&#xff0c;由 Linus Torvalds 于 2005 年开发&#xff0c;主要用于源代码管理。Git 允许多名开发者共同合作处理同一个项目&#xff0c;跟踪每个文件的修改&#xff0c;并且在必要时回滚到之前的版本。 Linus Torvalds是Linux…

CAC 2.0融合智谱AI大模型,邮件安全新升级

在数字化时代&#xff0c;电子邮件的安全问题日益成为关注的焦点。Coremail CACTER邮件安全人工智能实验室&#xff08;以下简称“CACTER AI实验室”&#xff09;凭借其在邮件安全领域的深入研究与创新实践&#xff0c;不断推动技术进步。 此前&#xff0c;CACTER AI实验室已获…

Python基础教程(二十八):pip模块

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

Go语言开发框架GoFly已集成数据可视化大屏开发功能,让开发者只专注业务开发,本文指导大家如何使用

前言 框架提供数据大屏开发基础&#xff0c;是考虑当前市场软件应用有一大部分是需要把业务数据做出大屏&#xff0c;很多政府项目对大屏需求特别高&#xff0c;还有生产企业项目也对大屏有需求&#xff0c;没有提供基础规范的后台框架&#xff0c;在开发大屏需要很多时间去基…

Ubuntu server 24 (Linux) 安装部署samba服务器 共享文件目录 windows访问

1 安装 sudo apt update sudo apt-get install samba #启动服务 sudo systemctl restart smbd.service sudo systemctl enable smbd.service #查看服务 2 创建用户 #创建系统用户 sudo useradd test2 #配置用户密码 sudo smbpasswd -a test2 # smbpasswd: -a添加用户 …

STM32学习笔记(六)--引脚重映射详解

STM32F103C8T6引脚定义&#xff1a; 在STM32微控制器中&#xff0c;外设引脚的复用功能&#xff08;Alternate Function&#xff0c;AF&#xff09;有时会出现冲突&#xff0c;例如当USART2_CTS和TIM2_CH1同时需要使用相同的引脚时。此时&#xff0c;可以通过引脚重映射功能&am…

DS知识点总结--线性表定义及顺序表示

数据结构知识点汇总(考研C版) 文章目录 数据结构知识点汇总(考研C版)二、线性表2.1 线性表的定义和操作2.1.1 线性表的定义2.1.2 线性表的基本操作 2.2 线性表的顺序表示2.2.1 顺序表的定义2.2.2 顺序表上的基本操作的实现 二、线性表 2.1 线性表的定义和操作 2.1.1 线性表的…

python通过selenium实现自动登录及轻松过滑块验证、点选验证码(2024-06-14)

一、chromedriver配置环境搭建 请确保下载的驱动程序与你的Chrome浏览器版本匹配&#xff0c;以确保正常运行。 1、Chrome版本号 chrome的地址栏输入chrome://version&#xff0c;自然就得到125.0.6422.142 版本 125.0.6422.142&#xff08;正式版本&#xff09; &#xff08;…

V4和V6双栈处理

现进行双栈 对R1 对R2 对R3 对R4 路由地址配完&#xff0c;起协议 然后起ripng&#xff0c;在R2&#xff0c;R3&#xff0c;R4上都宣告一下 然后在PC1和PC2上都手动配置一下就可以了

Kafka第一篇——内部组件概念架构启动服务器zookeeper选举以及底层原理

目录 引入 ——为什么分布式系统需要用第三方软件&#xff1f; JMS 对比 组件 架构推演——备份实现安全可靠 &#xff0c; Zookeeper controller的选举 controller和broker底层通信原理 BROKER内部组件 ​编辑 topic创建 引入 ——为什么分布式系统需要用第三方软件&#…