论QT6多线程技术

前言

以前我多线程使用传统的继承qthread重写run()或者继承qrunable类把对象丢到线程池解决。经过昨天的面试让我了解到新的技术,我之前看到过只不过没有详细的去了解movetotread技术,这个技术是qt5推出的,qt6还在延续使用

代码结构

以下是简单的movetotread的实现

class Worker:public QObject{
Q_OBJECT
private slots:
dowork();/*业务逻辑*/
}//使用方式
QThread thread;
Worker woker;
woker.movetotread(&tread);
thread.start();
//通过信号触发work
QObject::connect(&sender,&sender::startsignal,&worker,&worker::doworke);

实现逻辑

movetotread实现了线程与事务相分离,但需要运行某个事件的时候只需要将继承了QObject类的对象通过movetotread(&目标线程)传进去执行,通过qdequeueconnect()实现跨线程通讯。

关键操作

初次创建线程的时候通过start()函数,它会调用run()函数并启动事件循环(默认exec())

退出线程有三种

thread->quit();//优雅退出
tread->wait();//主线程阻塞等待子线程结束
thread->terminate();//强制退出线程,不推荐这种,可能导致线程未释放

创建好线程以后可以写两个connect管理对象和线程当线程执行完时释放finished信号来管理对象和线程的生命周期

connect(thread,&qthread::finished,worker,&QObject::deletelater);
connect(thread,&qthread::finished,thread,&QObject::deletelater);

跨线程的时候不要直接调用对象内的方法,可以通过主线程connect信号触发worker->doworker();

其他注意细节

如果线程未被释放,是可以通过movetothread将新的对象传进去。

如果向一个线程里面重复movetothread,最新的对象会把上一个对象给替代掉。

小实验

我设计两个线程,一个是主线程,里面是mainwindow,一个是子线程,专门生产1-6的随机数,生产好了以后将生成的数字传递到主线程显示出来

首先是建一个随机数生成器类randomnum

//头文件
#ifndef RANDOMNUM_H
#define RANDOMNUM_H
#include<QObject>
#include<QRandomGenerator>
#include<QTimer>class randomnum : public QObject
{Q_OBJECT
public:explicit randomnum(QObject *parent = nullptr);
public slots:void startrandom();//开始生成随机数void stoprandom();//暂停生成
signals:void newnumber(int count,int number);
private:QTimer *timer;//计时器int count=0;//计数QRandomGenerator random;//随机数生成器
};#endif // RANDOMNUM_H
//cpp
#include "randomnum.h"
#include "qobject.h"randomnum::randomnum(QObject *parent): QObject{parent}
{timer=new QTimer(this);connect(timer,&QTimer::timeout,this,[this](){count++;int num=random.bounded(1,6);emit newnumber(count,num);});
}void randomnum::startrandom()
{timer->start(1000);
}void randomnum::stoprandom()
{timer->stop();
}

主程序

//头文件
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;QThread *thread1;private slots:void appendnum(int count,int num);};
#endif // MAINWINDOW_H
//cpp文件
#include "randomnum.h"
#include "ui_mainwindow.h"
#include<QString>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->plainTextEdit->setReadOnly(true);//创建工作对象和线程randomnum *random1=new randomnum;thread1=new QThread(this);//把工作对象移动到子线程random1->moveToThread(thread1);//连接信号槽//触发开始随机数的信号//connect(thread1,&QThread::started,random1,&randomnum::startrandom);//把子线程生成的信号参数传给主线程对应的槽函数connect(random1,&randomnum::newnumber,this,&MainWindow::appendnum);//开始按钮connect(ui->btnstart,&QPushButton::clicked,random1,&randomnum::startrandom);//暂停按钮connect(ui->btnstop,&QPushButton::clicked,random1,&randomnum::stoprandom);//管理对象生命周期connect(thread1,&QThread::finished,random1,&QObject::deleteLater);//connect(thread1,&QThread::finished,thread1,&QObject::deleteLater);thread1->start();
}MainWindow::~MainWindow()
{if(thread1&&thread1->isRunning()){thread1->quit();thread1->wait();}delete ui;
}void MainWindow::appendnum(int count, int num)
{QString str=QString("第%1次,数字是%2").arg(count).arg(num);ui->plainTextEdit->appendPlainText(str);
}

显示效果

程序怎么实现的看上面代码就行了,这里讲下遇到的问题:

1.关闭程序,程序崩溃,子线程没有停止导致的,刚开始的时候明明有一个connect连接finished的信号,结果还是没关掉,原因是deletlater只是标记了他为待删除,不需要这一句,直接在析构函数里面显示删除,之前那一句不要了,避免重复删除

2.添加开始/停止按钮,用这个直接操作计时器,不是操控线程就可以实现 

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

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

相关文章

VTEP是什么

VTEP&#xff08;VXLAN Tunnel Endpoint&#xff0c;VXLAN 隧道端点&#xff09;是 VXLAN&#xff08;Virtual Extensible LAN&#xff09;网络中的关键组件&#xff0c;用于处理 VXLAN 流量的封装和解封装。以下以可读的 Markdown 格式详细解释 VTEP 的定义、功能、实现方式以…

antdv3 Tabs.TabPane 右上角增加一个角标Badge

1、Tabs官方说明 Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js 2、Badge角标官方效果图 Ant Design Vue — An enterprise-class UI components based on Ant Design and Vue.js 3、Tabs.TabPane要实现的效果 4、代码 <Tabs v-m…

浅析 Spring 启动过程:从源码到核心方法

浅析 Spring 启动过程&#xff1a;从源码到核心方法 一、Spring 注解方式启动类 Demo二、Spring 启动过程源码解析​AnnotationConfigApplicationContext构造函数refresh()方法详解 三、refresh()的核心方法/步骤obtainFreshBeanFactory() - 获取Bean工厂prepareBeanFactory(be…

贝叶斯优化Transformer融合支持向量机多变量回归预测,附相关性气泡图、散点密度图,Matlab实现

贝叶斯优化Transformer融合支持向量机多变量回归预测&#xff0c;附相关性气泡图、散点密度图&#xff0c;Matlab实现 目录 贝叶斯优化Transformer融合支持向量机多变量回归预测&#xff0c;附相关性气泡图、散点密度图&#xff0c;Matlab实现效果一览基本介绍程序设计参考资料…

智慧化系统安全分析报告

智慧化系统的安全背景与现状 一、政策法规背景 &#xff08;一&#xff09;全球主要国家/地区政策对比 地区政策名称核心内容实施时间特点中国《生成式人工智能服务管理暂行办法》明确服务提供者责任&#xff0c;强调数据合法、隐私保护&#xff0c;禁止生成违法内容2023年8…

【学习笔记】点云自动化聚类简要总结

聚类是将将具有相似特征划分为相同点集的操作。 基于空间邻近性的方法 核心思想&#xff1a;依据点的空间距离进行分组 欧式聚类&#xff08;DBSCAN&#xff0c;KD-tree) 原理&#xff1a;基于半径搜索和最小点数扩展簇。 优点&#xff1a;适应不规则形状&#xff0c;无需预…

全志F10c200开发笔记——移植uboot

相关资料&#xff1a; &#xff08;二&#xff09;uboot移植--从零开始自制linux掌上电脑&#xff08;F1C200S)&#xff1c;嵌入式项目&#xff1e;-CSDN博客 F1C200S挖坑日记&#xff08;3&#xff09;——Uboot编译篇_f1c200s uboot-CSDN博客 一、安装编译器 Linaro Rele…

常见WEB漏洞----暴力破解

什么是暴力破解 暴力破解 (Brue Force) 是一种攻击方法 (穷举法)&#xff0c;简称为“爆破”&#xff0c;黑客通过反复猜解和实验&#xff0c;旨在以暴力手段登入、访问目标主机获取服务&#xff0c;破坏系统安全&#xff0c;其属于 ATT&CK技术中的一种&#xff0c;常利用…

ARM A64 LDR指令

ARM A64 LDR指令 1 LDR (immediate)1.1 Post-index1.2 Pre-index1.3 Unsigned offset 2 LDR (literal)3 LDR (register)4 其他LDR指令变体4.1 LDRB (immediate)4.1.1 Post-index4.1.2 Pre-index4.1.3 Unsigned offset 4.2 LDRB (register)4.3 LDRH (immediate)4.3.1 Post-index…

2.安卓逆向2-adb指令

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…

Obsidian Callouts标注框语法

Obsidian 从 0.14 版本开始原生支持 Callouts&#xff1a; 语法基于 Markdown 引用块&#xff08;>&#xff09;扩展&#xff1a; 语法格式如下&#xff1a; > [!类型] 可选标题 > 内容支持 **Markdown 格式**、[[内部链接]] 和嵌入文件。预览 可选类型一览&#xf…

nt!MiAllocateWsle函数分析之设置Wsle[WorkingSetIndex]

第一部分&#xff1a; 1: kd> p nt!MiAddValidPageToWorkingSet0xa9: 80a83c13 e8da9afcff call nt!MiAllocateWsle (80a4d6f2) 1: kd> t nt!MiAllocateWsle: 80a4d6f2 55 push ebp 1: kd> dv WsInfo 0x8953a1f8 PointerPte …

docker 命令操作大全

1 Docker Hello World 简单命令 docker run ubuntu:15.10 /bin/echo "Hello world" docker run&#xff1a;启动一个新容器。 ubuntu:15.10&#xff1a;使用的 Docker 镜像&#xff08;Ubuntu 15.10 版本&#xff09;。 Docker 首先从本地主机上查找镜像是否存在&a…

【软件工程】基于机器学习的多缺陷定位

基于机器学习的多缺陷定位&#xff08;Multi-Dault Localization, MDL&#xff09;是软件工程和自动化测试领域的重要研究方向&#xff0c;旨在通过机器学习技术高效识别代码中多个潜在缺陷的位置。以下从方法、挑战、应用场景及未来方向展开分析&#xff1a; 一、核心方法 监督…

用MCP往ppt文件里插入系统架构图

文章目录 一、技术架构解析1. Markdown解析模块(markdown_to_hierarchy)2. 动态布局引擎(give_hierarchy_positions)3. PPTX生成模块(generate_pptx)二、核心技术亮点1. 自适应布局算法2. MCP服务集成三、工程实践建议1. 性能优化方向2. 样式扩展方案3. 部署实践四、应用…

CS016-2-unity ecs

目录 【23】射击改进 【24】僵尸生成器 ​编辑【25】随机行走 【27】射击光效 【23】射击改进 a. 当距离目标太远的时候&#xff0c;要继续移动。而当距离目标到达攻击距离之后&#xff0c;则停止移动。 上图中的if&#xff1a;判断自身和目标的距离是否大于攻击距离&#…

新能源汽车制动系统建模全解析——从理论到工程应用

《纯电动轻卡制动系统建模全解析&#xff1a;车速-阻力拟合、刹车力模型与旋转质量转换系数优化》 摘要 本文以纯电动轻卡为研究对象&#xff0c;系统解析制动系统建模核心参数优化方法&#xff0c;涵盖&#xff1a; 车速-阻力曲线拟合&#xff08;MATLAB实现与模型验证&…

函数专题1

函数的定义 函数的基本写法如下所示&#xff1a; def function_name(parameter1, parameter2, ...):"""Docstring: 描述函数的功能、参数和返回值 (可选但强烈推荐)"""# 函数体: 实现功能的代码# ...return value # 可选&#xff0c;用于返回结…

红黑树:数据世界的平衡守护者

在 C 算法的神秘森林里&#xff0c;红黑树是一棵充满智慧的 “魔法树”。它既不像普通二叉搜索树那样容易失衡&#xff0c;也不像 AVL 树对平衡要求那么苛刻。作为 C 算法小白&#xff0c;今天就和大家一起深入探索红黑树的奥秘&#xff0c;看看它是如何成为数据世界的平衡守护…

【hot100-动态规划-139.单词拆分】

力扣139.单词拆分 本题要求判断给定的字符串 s 是否可以被空格拆分为一个或多个在字典 wordDict 中出现的单词,且不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用,这是一个典型的动态规划问题。 动态规划思路 定义状态: 定义一个布尔类型的数组 dp,其中…