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

Qt学习笔记(四)多线程

系列文章目录

Qt开发笔记(一)Qt的基础知识及环境编译(泰山派)
Qt学习笔记(二)Qt 信号与槽
Qt学习笔记(三)网络编程
Qt学习笔记(四)多线程


文章目录

  • 系列文章目录
  • 前言
  • 一、QThead
    • 1.1 QThead的引入
    • 1.2 相关API
    • 1.3 QThread的工作流程
  • 二、继承QThread的代码实现


前言

  在Qt中,多线程的处理一般是通过QThread类来实现。QThread代表一个在应用程序中可以独立控制的线程,也可以和进程中的其他线程共享数据。之前我们在Linux应用篇中提到过多线程的概念,使用它的好处是可以同时操作好几个目标,而不是因为上一个目标未结束使得需要的操作陷入阻塞状态。


一、QThead

1.1 QThead的引入

  QThread 提供了线程启动、停止以及与其他对象通信的能力,我们可以利用主线程用于处理 GUI 操作,而长时间的耗时任务(如文件 I/O、网络请求、大数据处理等)可以放到其他线程中去执行,从而避免界面卡顿现象。QThread 是 Qt 提供的一个线程管理类,封装了原生的线程接口,使得线程的创建、启动、终止和通信更加直观和方便。
  QThread 线程类是实现多线程的核心类。Qt有两种多线程的方法,其中一种是继承QThread的run()函数,另外一种是把一个继承于QObject的类转移到一个Thread里。两种方法区别不大,用起来都比较方便,但继承QObject的方法更加灵活,笔者这里偏向前者。
继承QThread
  继承QThread是创建线程的一个普通方法。其中创建的线程只有run()方法在线程里的。其他类内定义的方法都在主线程内。
在这里插入图片描述
  通过上面的图我们可以看到,主线程内有很多方法在主线程内,但是子线程,只有 run()方法是在子线程里的。run()方法是继承于QThread类的方法,用户需要重写这个方法,一般是把耗时的操作写在这个run()方法里面。
继承QObject的线程
在这里插入图片描述
  与上一种方法不同,我们先写一个类继承 QObject,通过QObject::moveToThread()方法将它移到一个QThread线程里执行。那么可以通过主线程发送信号去调用QThread线程的方法如上图的fun4(),fun5()等等。这些方法都是在QThread线程里执行的。

1.2 相关API

函数名描述
run()线程入口函数
start()通过调用run()函数开始执行线程,操作系统根据优先级参数调度线程
currentThread()返回一个指向 管理当前执行线程 的QThread的指针
isRunning()若线程正在运行返回true,否则返回false
sleep()/msleep()/usleep()实现线程休眠,单位为秒/毫秒/微秒
wait()阻塞线程
quit()请求线程退出事件循环,常用于安全关闭线程。
finished()当线程结束时会发出该信号,可以通过该信号来实现线程的清理工作

注:使用wait()函数后,线程会阻塞至直到满足以下任何一个条件:

  • 与此QThread对象关联的线程已经完成执行(即当它从run()返回时),若线程已经完成,这个函数将返回true;若线程尚未启动,也返回true;
  • 已经过了几毫秒,若时间是ULONG_MAX(默认值),那么等待永远也不会超时(线程必须从run()返回),若等待超时,此函数返回false与POSIX pthread_join() 函数类似terminate()| 终止线程的执行。线程可以立即终止,也可以不立即终止,取决于操作系统的调度策略。在terminate()之后使用QThread::wait()来确保终止

1.3 QThread的工作流程

  就像前面提到的,笔者偏向继承QThread的写法,这里以这种为主。QThread 的核心流程是创建一个线程对象,将任务移动到该线程,然后启动线程以执行任务。QThread 内部维护了一个事件循环,确保线程可以响应事件和信号槽的触发。线程启动时自动调用 run() 方法,线程结束时会发送 finished 信号。

  1. 定义一个类继承 QThread 并重写 run() 函数
  2. 线程处理函数里面写入需要执行的复杂数据处理,需要注意以下几点:
     - 确定 run() 函数需要执行的具体数据处理任务,例如文件读取、数据分析、图像处理、网络请求等。
     - 处理流程设计:在 run() 中合理设计任务处理流程,比如是否需要循环、数据的预处理和后处理、错误处理等。
     - 线程间通信:在任务处理过程中,可能需要将进度、结果或错误状态传递回主线程。可以使用信号槽机制实现这些交互。
     - 资源释放:确保在任务完成时清理分配的资源,以防止内存泄漏或资源占用。
  3. 使用对象调用 start() 函数来启动线程
  4. 定义一个信号通知主线程执行完成
  5. 线程关闭与资源清理

二、继承QThread的代码实现

  代码部分也是利用前段时间写的毕设拯救计划(二)基于QT的智能家居(Onenet云)中的代码演示,它主要是在 Qt 中使用 QThread 可以让 DHT11 的数据读取在后台线程中执行,从而避免阻塞主界面线程。如果大家不会dht11的话可以看一下笔者之前写的驱动Linux驱动开发笔记(五) 基于设备树与GPIO子系统(含单总线)的操作实验。
  首先,新建一个类 DHT11ReaderThread,继承 QThread 并实现数据读取逻辑。

// dht11readerthread.h
#ifndef DHT11READERTHREAD_H
#define DHT11READERTHREAD_H#include <QThread>
#include <QString>class DHT11ReaderThread : public QThread
{Q_OBJECTpublic:DHT11ReaderThread(QObject *parent = nullptr);~DHT11ReaderThread();protected:// QThread 的主执行函数,前面提到了我们采用的方式主要是在run函数上void run() override; signals:// 用于发送新数据的信号void newData(QString temperature, QString humidity); private:// 用于控制线程的运行状态bool keepRunning; 
};#endif // DHT11READERTHREAD_H

  在 dht11readerthread.cpp的run函数中实现 DHT11 的数据读取逻辑,并在读取到数据后通过信号发送给主线程。

// dht11readerthread.cpp
#include "dht11readerthread.h"
#include "dht11.h"
#include <QDebug>DHT11ReaderThread::DHT11ReaderThread(QObject *parent): QThread(parent), keepRunning(true)
{dht11_init(); // 初始化 DHT11
}DHT11ReaderThread::~DHT11ReaderThread()
{keepRunning = false;dht11_close(); // 关闭 DHT11
}void DHT11ReaderThread::run()
{while (keepRunning) {char temperature;char humidity;// 读取 DHT11 数据if (dht11_read(&humidity, &temperature) == 0) {// 将读取到的数据格式化为字符串QString tempStr = QString("%1°C").arg((int)temperature);QString humiStr = QString("%1%").arg((int)humidity);// 发出信号,传递新数据emit newData(tempStr, humiStr);} else {qDebug() << "Failed to read data from DHT11.";}// 设置线程休眠 5 秒,控制读取频率msleep(5000);}
}

  在 MainWindow 的头文件中声明 updateDisplay 槽函数,用于接收来自线程的温湿度数据并更新 UI。

// mainwindow.h#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void updateDisplay(const QString &temperature, const QString &humidity); // 更新显示的槽函数private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

  在 MainWindow 中创建 DHT11ReaderThread 的实例,并连接信号以更新 QTextBrowser。

// mainwindow.cpp#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dht11readerthread.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 创建 DHT11 读取线程实例DHT11ReaderThread *readerThread = new DHT11ReaderThread(this);// 连接线程的信号到更新 QTextBrowser 的槽connect(readerThread, &DHT11ReaderThread::newData, this, &MainWindow::updateDisplay);// 启动线程readerThread->start();
}MainWindow::~MainWindow()
{delete ui;
}// 更新 QTextBrowser 显示的槽函数
void MainWindow::updateDisplay(const QString &temperature, const QString &humidity)
{QString displayText = QString("Temperature: %1\nHumidity: %2").arg(temperature).arg(humidity);ui->textBrowser->setText(displayText);
}

注:这里强调一下,不要在main.cpp和mainwindow.cpp中重复实例化对象。


免责声明:本文参考了网上公开的部分资料,仅供学习参考使用,若有侵权或勘误请联系笔者

相关文章:

Qt学习笔记(四)多线程

系列文章目录 Qt开发笔记&#xff08;一&#xff09;Qt的基础知识及环境编译&#xff08;泰山派&#xff09; Qt学习笔记&#xff08;二&#xff09;Qt 信号与槽 Qt学习笔记&#xff08;三&#xff09;网络编程 Qt学习笔记&#xff08;四&#xff09;多线程 文章目录 系列文章…...

java的小数计算如何保证精度不丢失

前言 学java的肯定都知道&#xff0c;要保证小数运算精度不丢失我们得用BigDecimal对象。这篇文章就分析一下为什么用浮点数会造成精度丢失&#xff1f;BigDecimal是怎么解决精度丢失问题的?下面我们一起看看吧&#xff01; 浮点数的表示 浮点数在计算机中通常采用 IEEE 75…...

分布式----Ceph应用(下)

目录 创建 Ceph 对象存储系统 RGW 接口 1、对象存储概念 2、创建 RGW 接口 //在管理节点创建一个 RGW 守护进程&#xff08;生产环境下此进程一般需要高可用&#xff0c;后续介绍&#xff09; //开启 httphttps &#xff0c;更改监听端口 //创建 RadosGW 账户 //S3 接口…...

小鹏汽车嵌入式面试题及参考答案

static 变量放在哪个段中? 在 C 和 C++ 等编程语言中,static 变量根据其定义的位置不同放置的段也不同。对于全局的静态变量(在函数体外定义的静态变量),它会被放在数据段(.data 段或者.bss 段)。如果这个静态变量被初始化了非零值,那么它会被放在.data 段,这个段存储…...

qt5半成品飞机大战小游戏

最近在学Qt&#xff0c;心血来潮做了个飞机大战小游戏&#xff0c;由于一些资源比较难找&#xff0c;就做了个半成品。效果图如下&#xff1a; 目前已做功能&#xff1a;人物飞机的自由移动&#xff0c;子弹的发射&#xff0c;子弹与敌机的物体碰撞,碰撞特效。 缺少功能&#x…...

一文速学---红黑树

文章目录 一、红黑树简介二、 红黑树特性三、红黑树插入3.1 红黑树为空3.2 父节点为黑色3.3 父节点为红色3.3.1 父亲和叔叔都是红色3.3.2 父节点为红色&#xff0c;叔叔节点为黑色3.3.2.1 父节点在左节点&#xff0c;插入节点在父亲左节点3.3.2.2 父节点在左节点&#xff0c;插…...

【graphics】图形绘制 C++

众所周知&#xff0c;周知所众&#xff0c;图形绘制对于竞赛学僧毫无用处&#xff0c;所以这个文章&#xff0c;专门对相关人员教学&#xff08;成长中的码农、高中僧、大学僧&#xff09;。 他人经验教学参考https://blog.csdn.net/qq_46107892/article/details/133386358?o…...

全志科技嵌入式面试题及参考答案

C 语言的编译过程是怎样的? C 语言的编译过程主要包括以下几个阶段。 首先是预处理阶段。在这个阶段,预处理器会处理以 “#” 开头的预处理指令。比如 #include 指令会把指定的头文件内容插入到当前的源文件中,这使得我们可以在程序中使用标准库函数或者自定义头文件中的声明…...

html 图片转svg 并使用svg路径来裁剪html元素

1.png转svg 工具地址: Vectorizer – 免费图像矢量化 打开svg图片,复制其中的path中的d标签的路径 查看生成的svg路径是否正确 在线SVG路径预览工具 - UU在线工具 2.在html中使用svg路径 <svg xmlns"http://www.w3.org/2000/svg" width"318px" height…...

Wallpaper壁纸制作学习记录01

导入图像 打开wallpaper软件&#xff0c;找到下方的播放列表&#xff0c;选择壁纸编辑器。 弹出下列界面&#xff0c;在创建壁纸处可以选择图片拖入。 在开始导入任何图像之前&#xff0c;请首先确保主背景图像表示实际屏幕分辨率。展示示例图像是 1920 x 1080&#xff0c;这…...

【深度学习】wsl-ubuntu深度学习基本配置

配置pip镜像源 这里注意一点&#xff0c;你换了源之后就最好不要开代理了&#xff0c;要不然搞不好下载失败&#xff0c;pip和conda都是 ## 配置中科大镜像 pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/web/simple# 配置阿里源 pip config set global…...

1000+ 道 Java面试题及答案整理(2024最新版)

作为 Java 程序员&#xff0c;选择学习什么样的技术&#xff1f;什么技术该不该学&#xff1f;去招聘网站上搜一搜、看看岗位要求就十分清楚了&#xff0c;自己具备的技术和能力&#xff0c;直接影响到你工作选择范围和能不能面试成功。 如果想进大厂&#xff0c;那就需要在 Ja…...

【java】抽象类和接口(了解,进阶,到全部掌握)

各位看官早安午安晚安呀 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连&#xff0c;小编尽全力做到更好 欢迎您分享给更多人哦 大家好我们今天来学习Java面向对象的的抽象类和接口&#xff0c;我们大家庭已经来啦~ 第一次复习时总结&#xff1a; 一&#xff1a;抽象类 1.1…...

量化交易系统开发-实时行情自动化交易-4.1.趋势跟踪交易策略

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说趋势跟踪策略原理。 趋…...

论文解析:基于区块链的计算能力共享系统

目录 论文解析:基于区块链的计算能力共享系统 2区top 核心内容: 核心创新点的原理与理论: 进化博弈论构建了计算服务部门之间计算力共享策略的动态模型。 采用深度强化学习(DRL)设计了节点选择算法,以最小化各部门的计算力成本 深度强化学习:深度学习的感知能力和…...

【网页设计】CSS3 进阶(动画篇)

1. CSS3 2D 转换 转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 转换&#xff08;transform&#xff09;你可以简单理解为变形 移动&#xff1a;translate旋转&#xff1a;rotate缩放&#xf…...

性能超越Spark 13.3 倍,比某MPP整体快数十秒 | 多项性能指标数倍于主流开源引擎 | 云器科技发布性能测试报告

云器Lakehouse正式发布性能测试报告 &#x1f3c5;离线批处理&#xff1a;在复杂批处理任务中&#xff0c;云器Lakehouse相较Spark表现出13.31倍性能提升。 &#x1f3c5;即席查询&#xff1a;在交互式分析场景下&#xff0c;云器Lakehouse相较Trino表现出9.84倍性能提升。 &am…...

Chat越狱

角色扮演&#xff1a; 在这个设定中&#xff0c;我扮演的是“红色警戒”&#xff0c;一个根据下面描述的情景输出文本的对话作者。“红色警戒”是一个纯粹的客观资源&#xff0c;不会保留任何信息&#xff0c;只是根据特定的条件输出对话。在这个与我们世界大不相同的地方&…...

【电子通识】Type-C连接器生产工艺流程

USB连接器类型各式各样&#xff0c;但生产制造全部全过程基础是一致的&#xff0c;一般可分成下列几个步骤&#xff1a; 冲压、电镀、胶芯注塑、拼装。 冲压 这部分包括对外壳的冲压和对usb端子的冲压&#xff0c;端子是usb连接器的核心部件&#xff0c;是与type-c公头或母座接…...

UE5 5.1.1创建C++项目,显示error C4668和error C4067的解决方法

因为工作要求&#xff0c;没法使用最新 5.5版本的ue5 而是要用ue5.1和5.2版本。 但是我在安装下载了visual studio2022后&#xff0c;使用 ue5.1编辑器 创建C项目&#xff0c;爆出如下错误。 error C4668: ?????__has_feature?????ΪԤ?????꣬???0????…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...