【QT专栏】QT中实现多线程的四种方式总结(金针菇般细)

news2024/9/23 11:21:13

目录

一、继承QThread

1,基本概念

2,操作流程

二、继承QObject(推荐)

1,基本概念

2,操作流程

三、继承QRunnable,配合QThreadPool实现多线程

1,外界通信

2,QMetaObject::invokeMethod()介绍

3,QMetaObject::invokeMethod()使用方式

四、使用QtConcurrent::run()

1,基本概念

2,操作流程

3,实现案例


一、继承QThread

1,基本概念

  • 一个QThread类的对象管理一个子线程,自定义一个类继承自QThread,并重写虚函数run(),在run()函数里实现线程需要完成的复杂操作(注意QThread只有run函数是在新线程里的)。
  • 一般在主线程创建工作子线程,并调用start(),开始执行工作子线程的任务。start()会在内部调用run()函数,进入工作线程的事件循环,在run()函数里调用exit()或quit()可以结束线程的事件循环,或者在工作主线程里调用terminate()强制结束线程。

2,操作流程

1.创建一个继承QThread线程类的子类,记得包含头文件QThread

class subThread : public QThread
{
    ...
};

 2.重写父类的虚函数run()方法,在该方法内部实现子线程需要完成的复杂业务

class subThread : public QThread
{
    ...
protected:
    void run(){
        //全部在这里处理子线程的复杂业务
    }
};

3.在主线程中创建子线程对象

subThread* st = new subThread;

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

st->start();

二、继承QObject(推荐)

1,基本概念

  • 如果有编写多个业务类,各不相关的业务逻辑需要被处理,就可以选择这种方式,将业务逻辑放入对应业务类的公共函数中,然后将这些业务类的实例对象移动到对应的子线程中moveToThread()就可以了,这种编写多线程的方式比第一种更加灵活,可读性也更强,更易于维护

2,操作流程

1.创建一个继承QObject类的子类,记得包含头文件QObject

class subObject : public QObject
{
    ...
}

2.在该类中添加一个公共的成员函数,主要负责子线程中要执行的业务逻辑

class subObject : public QObject
{
    ...
public:
    void working();    //函数名称随意取,传入的参数根据实际需求添加
}

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

QThread* subThread =  new QThread;

4.主线程中创建该类的对象(创建该类对象千万不要指定父对象)

subObject* subObj = new subObject(this);      //error
subObject* subObj = new subObject;            //OK

5.将工作类subObject对象移动到创建的子线程对象中,需要调用继承自QObject类提供的 moveToThread()方法

// void moveToThread(QThread *targetThread)
subObj->moveToThread(subThread);

6. 启动子线程,调用start()方法,但这时候并不会启动子线程的工作函数

subThread->start();

7.在主线程中通过信号槽调用线程类subObject对象的工作函数,这时候才会到子线程中运行该工作函数

connect(ui->pushButton,&QPushButton::clicked,subObj,&subObject::working);

参考文章 Qt中多线程的使用 | 爱编程的大丙

三、继承QRunnable,配合QThreadPool实现多线程

使用信号槽通信方式可以查看这篇文章 Qt中线程池的使用 | 爱编程的大丙

1,外界通信

  • QRunnable类是所有可运行对象的基类,没有继承于QObject,所以就不能使用信号槽功能与外界通信
  • 使用多继承,就是让线程类同时继承QObjectQRunnable(上述文章就使用这种方式,但不推荐,毕竟C#都是单继承的,不多解释啦),让该线程类能够支持信号槽的使用
  • 使用QMetaObject::invokeMethod()

2,QMetaObject::invokeMethod()介绍

  • 该静态函数调用 obj 对象上的成员如信号,槽名,Q_INVOKABLE声明的函数(能够被Qt元对象系统唤起,所以传入的第一个对象指针是QObject类型或QObject子类类型)。如果成员可以被调用,则返回true。如果没有这样的成员或形参不匹配,则返回false。
  • 调用可以是同步的,也可以是异步的,这取决于第三个参数类型ConnectionType:

Qt::DirectConnection
该成员将立即被调用,同步调用

Qt::QueuedConnection
一旦应用程序进入主事件循环,就会发送一个QEvent并调用成员,异步调用

Qt::BlockingQueuedConnection
该方法将以与Qt::QueuedConnection相同的方式被调用,除了当前线程将阻塞,直到事件被传递。使用这种连接类型在同一线程中的对象之间通信将导致死锁。

Qt::AutoConnection
如果obj与调用者位于同一个线程中,则同步调用成员;否则,它将异步调用成员。
  • 成员函数调用的返回值放在ret中,如果调用是异步的,则无法计算返回值。您最多可以向成员函数传递十个参数。
  • QGenericArgumentQGenericReturnArgument是内部的辅助类。因为信号和槽可以动态调用,所以必须使用Q_ARG()Q_RETURN_ARG()宏将参数括起来。Q_ARG()接受类型名和该类型的const引用,Q_RETURN_ARG()接受一个类型名和一个非const引用。

3,QMetaObject::invokeMethod()使用方式

1.线程类中通信的函数

Q_INVOKABLE void externalTonXin(QString info);

2.在重写虚函数run内加入该接口调用方式,参数m_obj为主线程对象指针,"externalTonXin"是要调用被Q_INVOKABLE声明的函数

QMetaObject::invokeMethod(m_obj,"externalTonXin",Q_ARG(QString,"子线程主线程通信..."));

3.在主线程创建线程对象时,需要将主界面对象(this)传入线程对象构造函数中

RunnableThread* st = new RunnableThread(this);

参考文章 Qt线程之QRunnable的使用详解

四、使用QtConcurrent::run()

1,基本概念

Qt Concurrent模块包含支持程序代码并发执行的功能,可以在不使用低级线程原语的情况下编写多线程程序,它是一个单独的模块,使用起来也非常简单,不用向上面三种那样去为了某个业务处理逻辑而编写线程类,这种方式只需要你把耗时的某个接口传入该接口就行,具有用法看下面

2,操作流程

1.在.pro文件中添加QT += concurrent

2.然后在耗时接口所在的头文件中包含QtConcurrent,并在所在源文件中调用QtConcurrent::run()

QtConcurrent::run(this,&QtConcurrentDemo::working);

3,实现案例

1.界面搭建,红色注释为个控件对象名称

2.头文件如下

#ifndef QTCONCURRENTDEMO_H
#define QTCONCURRENTDEMO_H

#include <QWidget>
#include <QDebug>
#include <QtConcurrent>

namespace Ui {
class QtConcurrentDemo;
}

class QtConcurrentDemo : public QWidget
{
    Q_OBJECT

public:
    explicit QtConcurrentDemo(QWidget *parent = nullptr);
    ~QtConcurrentDemo();

    void working();     //耗时接口,主线程中运行会阻塞,子线程中能正常运行

private:
    Ui::QtConcurrentDemo *ui;
    bool flag;  //控制线程开闭
};

#endif // QTCONCURRENTDEMO_H

3.源文件如下

#include "qtconcurrentdemo.h"
#include "ui_qtconcurrentdemo.h"

QtConcurrentDemo::QtConcurrentDemo(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QtConcurrentDemo)
{
    ui->setupUi(this);

    flag = false;
    connect(ui->startThread,&QPushButton::clicked,this,[=](){
        //耗时接口 working 在子线程中运行
        qDebug()<<__FUNCTION__<<QThread::currentThreadId();
        flag = true;
        QtConcurrent::run(this,&QtConcurrentDemo::working);
    });
    connect(ui->startNotThread,&QPushButton::clicked,this,[=](){
        //耗时接口 working 在主线程中运行
        qDebug()<<__FUNCTION__<<QThread::currentThreadId();
        flag = true;
        working();
    });
    connect(ui->closeThread,&QPushButton::clicked,this,[=](){
        //关闭线程
        qDebug()<<__FUNCTION__<<QThread::currentThreadId();
        flag = false;
        ui->label->setNum(0);
    });
}

QtConcurrentDemo::~QtConcurrentDemo()
{
    delete ui;
}

void QtConcurrentDemo::working()
{
    qDebug()<<__FUNCTION__<<QThread::currentThreadId();
    int i=0;
    while (flag) {
        ui->label->setNum(i++);
        qDebug()<<__FUNCTION__<<i;
        QThread::sleep(1);
    }
}

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

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

相关文章

SpringSecurity的安全认证的详解说明(附完整代码)

SpringSecurity登录认证和请求过滤器以及安全配置详解说明 环境 系统环境&#xff1a;win10 Maven环境&#xff1a;apache-maven-3.8.6 JDK版本&#xff1a;1.8 SpringBoot版本&#xff1a;2.7.8 根据用户名密码登录 根据用户名和密码登录&#xff0c;登录成功后返回Token数据…

狂神聊Redis复习笔记一

目录目前一个基本的互联网项目&#xff01;NoSQL 特点Redis 是什么&#xff1f;Redis 能干嘛&#xff1f;特性测试性能基础的知识Redis 是单线程的&#xff01;Redis 为什么单线程还这么快&#xff1f;五大数据类型Redis-KeyString&#xff08;字符串&#xff09;List&#xff…

[软件工程导论(第六版)]第3章 需求分析(复习笔记)

文章目录3.1 需求分析的任务3.2 与用户沟通获取需求的方法3.3 分析建模与规格说明3.4 实体-联系图&#xff08;E-R图&#xff09;3.5 数据规范化3.6 状态转换图3.7 其他图形工具3.8 验证软件需求需求分析是软件定义时期的最后一个阶段&#xff0c;需求分析的基本任务是准确的回…

EASYui+C#web

第一步创建一个web应用程序。 选择web应用程序。 第二步选择mvc框架 创建完成项目目录。 如图引入easyui包。 记住复制到content文件夹&#xff0c;否则无法识别。 easyui下载&#xff0c;官网。 如何用 引入jscss文件 <link rel"stylesheet" type"text…

Guitar Pro8手机电脑免费版吉他软件下载

Guitar Pro8是专业的吉他软件&#xff0c;具有可视化的五线谱编辑器&#xff0c;涵盖常用的乐器和特殊乐器单元&#xff0c;内置海量吉他音色效果和1000多个乐器音色&#xff0c;成为一个小型音乐站&#xff0c;制作出动听的音乐&#xff0c;支持边看边听&#xff0c;添加音频轨…

【论文阅读】 Few-shot object detection via Feature Reweighting

Few-shot object detection的开山之作之一 ~~ 特征学习器使用来自具有足够样本的基本类的训练数据来 提取 可推广以检测新对象类的meta features。The reweighting module将新类别中的一些support examples转换为全局向量&#xff0c;该全局向量indicates meta features对于检…

使用MindSpore20.0的API快速实现深度学习模型之数据变换

文章目录前言一. 实验环境二. 安装ubuntu虚拟机2. 1.下载ubuntu镜像2.2 配置虚拟机2.3 安装操作系统三. 安装MindSpore20.0-alpha3.1 下载需要的安装程序脚本3.2 安装MindSpore 2.0.0-alpha和Python 3.73.3 开始手动安装3.4. 安装gcc3. 5.安装MindSpore3.6. 验证是否成功&#…

【opencv源码解析0.3】调试opencv源码的两种方式

调试opencv源码的两种方式 上两篇我们分别讲了如何配置opencv环境&#xff0c;以及如何编译opencv源码方便我们阅读。但我们还是无法调试我们的代码&#xff0c;无法以我们的程序作为入口来一步一步单点调试看opencv是如何执行的。 【opencv源码解析0.1】VS如何优雅的配置ope…

有效提升英语论文写作的方法

这里结合我的一些经验&#xff0c;分享一些练习英语论文写作的方法。 论文是由单词&#xff0c;句子&#xff0c;还有逻辑三部分组成&#xff0c;每个部分的要求都不太一样&#xff0c;这里分成三个部分练习讨论: 1炼词, 2 炼句,3 炼逻辑. 炼词 首先&#xff0c;炼词就是首先…

发布npm库遇到的

&#xff08;1&#xff09;首先首先要检查源是npm还是淘宝镜像源&#xff0c;因为本地设置了淘宝镜像源的原因&#xff0c;会导致npm login出错&#xff0c;需要修改&#xff1a; npm config set registry https://registry.npmjs.org 查看是否修改成功&#xff1a;得到上面源…

SpringCloud - Eureka注册发现

目录 提供者与消费者 Eureka原理分析 搭建Eureka服务 服务注册 服务发现 提供者与消费者 服务提供者&#xff1a; 一次业务中&#xff0c;被其它微服务调用的服务(提供接口给其它微服务)服务消费者&#xff1a; 一次业务中&#xff0c;调用其它微服务的服务(调用其它微服务…

基于jeecgboot的flowable流程增加节点自动跳过功能

为了满足有时候需要在某个节点没有人员处理的时候需要自动跳过&#xff0c;所以增加了这个功能。 一、FlowComment意见里增加一个类型8&#xff0c;跳过流程 /** * 流程意见类型 * */ public enum FlowComment { /** * 说明 */ NORMAL("1", "…

Java8新特性全面

文章目录一、函数式接口二、Java内置函数式接口三、接口内允许添加默认实现的方法四、Lambda表达式五、方法引用六、Stream API七、Stream API示例1. Filter过滤2. Sorted排序3. Map转换4. Match匹配5. Count计数6. Reduce7. Parallel-Streams并行流8. Map集合八、新时间日期接…

天津+发展得到的权重

添加评分添加评分的依据高德地图找到如图数据&#xff0c;容积率体现楼层高度近似反映人口密度&#xff0c;繁华程度近似等价霓虹灯照明时长住房容积率具体是指在城市规划区的某一宗地内&#xff0c;房屋的总建筑面积与宗地面积的比值&#xff0c;分为实际容积率和规划容积率两…

链表学习基础

链表 通过指针串联在一起的线性结构&#xff0c;每个节点由数据域和指针域两部分组成。链表节点在内存中的存储通常不是连续的&#xff0c;各节点通过指针连接在一起&#xff0c;其内存分布大致如下图所示。 定义 单链表 struct ListNode {// DATATYPE 可以是任意存放数据的…

HTTP基础知识

关键字&#xff1a;一问一答用于和服务器交互什么是HTTPHTTP是个应用层协议&#xff0c;是HTTP客户端和HTTP服务器之间的交互数据格式。所以这里有个实例&#xff1a;在浏览网页的时候&#xff0c;浏览器会向服务器发送一个HTTP请求&#xff0c;告诉服务器我想访问什么..然后服…

图论学习03

图神经网络模型介绍 将图神经网络分为基于谱域上的模型和基于空域上的模型&#xff0c;并按照发展顺序详解每个类别中的重要模型。 基于谱域的图神经网络 谱域上的图卷积在图学习迈向深度学习的发展历程上起到了关键性的作用。三个具有代表性的谱域图神经网络 谱图卷积网络切…

c++中超级详细的一些知识,新手快来

目录 2.文章内容简介 3.理解虚函数表 3.1.多态与虚表 3.2.使用指针访问虚表 4.对象模型概述 4.1.简单对象模型 4.2.表格驱动模型 4.3.非继承下的C对象模型 5.继承下的C对象模型 5.1.单继承 5.2.多继承 5.2.1一般的多重继承&#xff08;非菱形继承&#xff09; 5.2…

奥地利、爱沙尼亚重要机构或正成为俄黑客目标

近日&#xff0c;网络安全公司Sekoia有一项新发现&#xff1a;由俄罗斯政府支持的黑客组织“图拉”&#xff08;Turla&#xff09;正在对奥地利经济商会、北约平台、波罗的海国防学院&#xff08;Baltic Defense College&#xff09;发动一系列攻击。这是Sekoia公司基于Google …

One Fuzzing Strategy to Rule Them All

One Fuzzing Strategy to Rule Them All 文章目录One Fuzzing Strategy to Rule Them All相关链接概述背景实验测试RQ1&#xff1a;RQ2相关工作总结最后相关链接 One Fuzzing Strategy to Rule Them All 参考链接 概述 在本文中作者提出了对变异策略havoc的研究&#xff0c…