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

QT 异步编程之多线程

一、概述

1、在进行桌面应用程序开发的时候,假设应用程序在某些情况下需要处理比较复制的逻辑,如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其它线程进行逻辑运算,多个线程各司其职,不仅可以提高用户体验还可以提升程序的执行效率。

2、当前的主线程不能让它做非常复制的逻辑操作,如果你让它做了非常复杂的逻辑操作后,咱们再操作这个窗口的时候就会出现界面的卡顿,那么这些复杂的操作应该交给子线程去做。

3、默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新。

4、子线程复制后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理。

5、主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号与槽机制

二、多线程的使用方式一

1、需要创建一个线程的子类,让其继承QT中的线程类QThread

class MyThread : public QThread
{...............
}

2、重写父类的run方法,在该函数内部编写子线程要处理的具体的业务流程

class MyThread : public QThread
{.........
protected:void run(){........}
}

3、在主线程中创建子线程对象,new一个就可以了

MyThread *subThread = new MyThread;

 4、启动子线程,调用start()方法

subThread->start();

5、示例 MyThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>
#include <QThread>class MyThread : public QThread
{Q_OBJECT
public:MyThread();void print();protected:void run() override;signals:
};#endif // MYTHREAD_H

6、 示例 MyThread.cpp

#include "mythread.h"
#include <QDebug>MyThread::MyThread()
{
}void MyThread::print()
{qDebug() << "子线程成员函数的线程ID:" << QThread::currentThreadId();
}void MyThread::run()
{qDebug() << "子线程的线程ID:" << QThread::currentThreadId();
}

7、main函数

int main(int argc, char *argv[])
{QApplication a(argc, argv);MyThread w;w.start();qDebug() << "主线程ID:" << QThread::currentThreadId();w.print();return a.exec();
}

8、结果展示

 9、结果分析:

(1)主线程和子线程的顺序不确定,偶尔主线程在前,偶尔子线程在前

(2)子线程类的成员函数包括槽函数是运行在主线程当中的,只有run()函数运行在子线程中

(3)如果run()函数中调用子线程的成员函数,那么该成员函数运行在子线程中

二、多线程的使用方式二

 1、创建一个新的类,让这个类从QObject派生

class MyWork : public QObject
{.........
}

2、在这个类中添加一个公共的成员函数,函数体就是我们要子线程中要执行的业务逻辑

class MyWork : public QObject
{
public:......//函数名自己指定,叫什么都可以void working();
}

3、在主线程中创建一个QThread对象,这就是子线程的对象

QThread *sub = new QThread;

4、在主线程中创建工作的类对象(不要给创建的对象指定父对象)

MyWork *work = new MyWork(this);  //error
MyWork *work = new MyWork;        //ok

5、将MyWork对象移动到创建的子线程对象中,需要调用QObject类提供的moveToThread()方法

work->moveToThread(sub);

6、启动子线程,调用start(),这时候线程启动了,但是移动到线程中的对象并没有工作

7、调用MyWork类对象的工作函数,让这个函数开始执行,这时候是在移动到的那个子线程中运行的

8、示例 MyWork.h

#ifndef MYWORK_H
#define MYWORK_H#include <QObject>class MyWork : public QObject
{Q_OBJECT
public:explicit MyWork(QObject *parent = nullptr);void print();public slots:void doWork();signals:
};#endif // MYWORK_H

9、示例 MyWork.cpp

#include "mywork.h"
#include <QDebug>
#include <QThread>MyWork::MyWork(QObject *parent): QObject{parent}
{
}void MyWork::print()
{qDebug() << "成员函数ThreadID:" << QThread::currentThreadId();
}void MyWork::doWork()
{qDebug() << "doWork ThreadId:" << QThread::currentThreadId();
}

10、示例 main

int main(int argc, char *argv[])
{QApplication a(argc, argv);QThread *thread = new QThread();MyWork *worker = new MyWork;worker->moveToThread(thread);QObject::connect(thread, &QThread::started, worker, &MyWork::doWork);QObject::connect(thread, &QThread::started, worker, &MyWork::print);qDebug() << "主线程ID:" << QThread::currentThreadId();//启动线程thread->start();//调用成员函数worker->print();return a.exec();
}

 11、运行结果

22:38:21: Starting D:\QT\practice\mouseTrack\bin\debug\untitled.exe...
主线程ID: 0x56f0
成员函数ThreadID: 0x56f0
doWork ThreadId: 0x49d4
成员函数ThreadID: 0x49d4

 12、结果分析

(1)通过信号与槽触发的成员函数、槽函数,执行都在新线程里面,通过对象调用执行,则在旧线程里面

三、QThread常用函数

1、start():启动线程,使线程进入运行状态

2、quit():终止线程的事件循环

3、terminate():强制终止线程的执行,不推荐使用,可能导致资源泄露和未定义的行为

4、wait():阻塞当前线程,直到线程执行完成或超时

5、finished():在线程执行完成时发出信号

6、isRunning():判断线程是否正在运行

7、currentThreadId:返回当前线程ID

8、setPriority:设置线程优先级

9、yieldCurrentThread():释放当前线程的时间片,允许其它线程执行

10、msleep():让当前线程休眠指定毫秒数

四、QThread的退出方式

1、重写run函数的方式退出,这个我们好控制。但是使用MoveToThread的方式,在退出线程的时候经常会碰到崩溃的情况,如下:

Destroyed while thread is still running 

2、说明线程还没有退出循环就被强制释放了资源,意思就是线程还在运行过程中被释放,就造成了崩溃。所以我们在给线程发出退出指令之后,还要等待线程执行完此次事件循环,再才能销毁这个thread指针。

//错误案例1
thread->quit();
delete trhead;//错误案例2
thread->terminate();
delete thread;

 上面都是不安全的代码,不要使用

3、安全的退出方式

(1)使用QThread的finished信号绑定QObject的deleteLater函数实现自动释放

	TestObject* object = new TestObject;QThread* thread = new QThread;object->moveToThread(thread );connect(thread,&QThread::finished,object,&TestObject::deleteLater);	// 退出后释放TestObject对象资源connect(thread,&QThread::finished,thread,&QThread::deleteLater);	// 退出后释放QThread对象资源thread->start();

(2)绑定函数退出

void MyWork::deleteThread(QThread *thread)
{thread->quit();thread->wait();delete thread;
}connect(myWoker, &MyWorker::signalFinished, myWoker, &QObject::deleteLater);
connect(myWoker, &QObject::destroyed, this, [thread, this]() { deleteThread(thread); });

五、两种方式的使用场景

1、QThread使用场景

(1)当需要创建一个独立的线程来执行某个任务,且需要对线程的整个生命周期进行管理时,适合使用 QThread 方式。

(2)当任务逻辑相对简单或独立,不需要频繁地进行线程间通信时,可以选择使用 QThread 方式。

2、moveToThread方式

(1)当需要将一个 QObject 对象移动到指定的线程中执行任务,或者需要多个对象在同一线程中协同工作时,适合使用 moveToThread() 方式。

(2)当需要灵活地控制对象和线程之间的关系,进行复杂的线程间通信时,可以选择使用 moveToThread() 方式。

相关文章:

QT 异步编程之多线程

一、概述 1、在进行桌面应用程序开发的时候&#xff0c;假设应用程序在某些情况下需要处理比较复制的逻辑&#xff0c;如果只有一个线程去处理&#xff0c;就会导致窗口卡顿&#xff0c;无法处理用户的相关操作。这种情况下就需要使用多线程&#xff0c;其中一个线程处理窗口事…...

K-均值(K-means)

K-均值&#xff08;K-means&#xff09;是一种常用的无监督学习算法&#xff0c;用于将数据集中的样本分成 K 个簇。该算法的过程大致如下&#xff1a; 1. 随机初始化 K 个聚类中心&#xff08;centroid&#xff09;。 2. 将每个样本分配到与其最近的聚类中心所代表的簇。 3. …...

AI agent 未来好的趋势:AI医疗影像、智能客服、个性化推荐

AI agent 未来好的趋势:AI医疗影像、智能客服、个性化推荐 目录 AI agent 未来好的趋势:AI医疗影像、智能客服、个性化推荐比特币AI Agents稳定币扩容区块链AI基础设施AI驱动的软件应用AI赋能的行业应用AI医疗影像、智能客服、个性化推荐AI药物研发比特币 市场与机构化:2024…...

接入 SSL 认证配置:满足等保最佳实践

前言 随着信息安全形势的日益严峻&#xff0c;等保&#xff08;信息安全等级保护&#xff09;要求成为各行业信息系统必须遵守的标准。在数据库领域&#xff0c;OpenGauss作为一款高性能、安全、可靠的开源关系型数据库&#xff0c;也需要满足等保要求&#xff0c;确保数据的安…...

微软AutoGen高级功能——Selector Group Chat

介绍 大家好&#xff0c;这次给大家分享的内容是微软AutoGen框架的高级功能Selector Group Chat(选择器群聊)&#xff0c;"选择器群聊"我在给大家分享的这篇博文的代码中有所体现微软AutoGen介绍——Custom Agents创建自己的Agents-CSDN博客&#xff0c;但是并没有详…...

w206基于Spring Boot的农商对接系统的设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…...

Springboot中使用Elasticsearch(部署+使用+讲解 最完整)

目录 引言 一、docker中安装Elasticsearch 1、创建es专有的网络 2、开放端口 3、在es-net网络上安装es和kibana 4、可能出现的问题 5、测试 6、安装IK分词器 7、测试IK分词器 二、结合业务实战 1、准备依赖 2、配置yml 3、读取yml配置 4、准备es配置类 5、编写测…...

深度求索—DeepSeek API的简单调用(Java)

DeepSeek简介 DeepSeek&#xff08;深度求索&#xff09;是由中国人工智能公司深度求索&#xff08;DeepSeek Inc.&#xff09;研发的大规模语言模型&#xff08;LLM&#xff09;&#xff0c;专注于提供高效、智能的自然语言处理能力&#xff0c;支持多种场景下的文本生成、对…...

flv实时监控视频

文章目录 前言一、安装二、引入三、使用 前言 开发大屏项目时&#xff0c;可能需要在大屏上展示一个监控画面&#xff0c;此时就可以用的flv.js来展示视频效果 一、安装 npm install flv.js二、引入 import flvjs from flv.js;三、使用 <video ref"videoElement&quo…...

有哪些免费的SEO软件优化工具

随着2025年互联网的不断发展&#xff0c;越来越多的企业意识到在数字营销中&#xff0c;网站的曝光度和排名至关重要。无论是想要提高品牌知名度&#xff0c;还是想要通过在线销售增加收益&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;都是一项不可忽视的关键策略。而要…...

跟着ai辅助学习vue3

第一章&#xff1a;基础入门&#xff08;1 - 2 周&#xff09; 1. 了解 Vue 3 概述 阅读官方文档简介 访问 Vue 3 官方文档&#xff0c;在首页或简介板块中&#xff0c;重点了解 Vue 3 相较于 Vue 2 的重大变革。比如&#xff0c;Vue 3 采用了 Proxy 实现响应式系统&#xff…...

什么是Mustache

Mustache 是一种轻量级模板引擎&#xff0c;用于将变量插入到模板中生成最终的文本输出。它的设计简单且易于使用&#xff0c;适用于多种编程语言&#xff0c;包括 JavaScript、Python、Ruby、Java 等。 Mustache 的模板语法使用双大括号 {{}} 包裹变量或表达式&#xff0c;用…...

C++,STL容器适配器,priority_queue:优先队列深入解析

文章目录 一、容器概览与核心特性核心特性速览二、底层实现原理1. 二叉堆结构2. 容器适配器架构三、核心操作详解1. 容器初始化2. 元素操作接口3. 自定义优先队列四、实战应用场景1. 任务调度系统2. 合并K个有序链表五、性能优化策略1. 底层容器选择2. 批量建堆优化六、注意事项…...

1.综述 Google 的软件工程读书笔记

Google 的软件工程由Google的多位资深工程师合著&#xff0c;分享了他们在管理Google庞大代码库&#xff08;超过20亿行代码&#xff09;过程中总结的经验教训。这本书不仅涵盖了软件工程的理论知识&#xff0c;还结合了Google的实际案例&#xff0c;展示了如何在大规模、复杂的…...

vue框架生命周期详细解析

Vue.js 的生命周期钩子函数是理解 Vue 组件行为的关键。每个 Vue 实例在创建、更新和销毁过程中都会经历一系列的生命周期阶段&#xff0c;每个阶段都有对应的钩子函数&#xff0c;开发者可以在这些钩子函数中执行特定的操作。 Vue 生命周期概述 Vue 的生命周期可以分为以下几…...

复杂电磁环境下无人机自主导航增强技术研究报告——地磁匹配与多源数据融合方法,附matlab代码

本文给出介绍和matlab程序&#xff0c;来实现地磁辅助惯性导航仿真验证&#xff0c;包含地磁基准图构建、飞行轨迹生成、INS误差建模、地磁匹配定位及多源数据融合等模块。通过对比分析验证地磁匹配修正惯性导航累积误差的有效性&#xff0c;可视化显示卫星拒止环境下的航迹修正…...

蓝桥杯---排序数组(leetcode第912题)

文章目录 1.题目重述2.思路分析3.代码解释 1.题目重述 题目的要求是不使用库函数或者是其他的内置的函数&#xff08;就是已经实现好的函数&#xff09;&#xff0c;也就是这个排序的逻辑需要我们自己进行实现&#xff1b; 2.思路分析 其实这个例子也是很容易理解的&#xff…...

考研高数复习规范

前言 这里记录我的高数复习规范与规划&#xff0c;希望能给需要考研的同学一点启发 规范原因 高数的内容很多&#xff0c;关键的是&#xff1a;会做题、拿高分首先最重要的就是抓住概念。比如有界无界的概念&#xff0c;间断点的概念、极限的概念其次是做题过程中得到的方法…...

Stable diffusion只换衣服的方法

大概看了几个帖子感觉说的都不是很清楚&#xff0c;也大部分都是保持人物一致性&#xff0c;不能只改变衣服&#xff0c;自己摸索了一下&#xff0c;需要使用三个controlnet&#xff1a;一个openpose、一个lineart&#xff0c;一个depth&#xff0c;三个controlnet使用同一个参…...

无人机航迹规划: 梦境优化算法(Dream Optimization Algorithm,DOA)求解无人机路径规划MATLAB

一、梦境优化算法 梦境优化算法&#xff08;Dream Optimization Algorithm&#xff0c;DOA&#xff09;是一种新型的元启发式算法&#xff0c;其灵感来源于人类的梦境行为。该算法结合了基础记忆策略、遗忘和补充策略以及梦境共享策略&#xff0c;通过模拟人类梦境中的部分记忆…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...