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)通过信号与槽触发的成员函数、槽函数,执行都在新线程里面,通过对象调用执行,则在旧线程里面

三、两种方式的使用场景

1、QThread使用场景

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

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

2、moveToThread方式

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

编码格式大全解释以及相关编码特性

目录 说明: 1. Base64 Base64编码的字符集通常包括&#xff1a; Base64的工作原理&#xff1a; Base64编码在安全渗透中的应用场景 常见的Base64编码绕过场景 如何防范Base64绕过攻击 2. URL编码&#xff08;Percent Encoding&#xff09; URL编码与安全渗透的关系 示…

软件工程-模块化设计

分解&#xff08;decomposition&#xff09; C&#xff08;P1P2&#xff09;> C&#xff08;P1&#xff09;C&#xff08;P2&#xff09; E&#xff08;P1P2&#xff09;> E&#xff08;P1&#xff09;E&#xff08;P2&#xff09; C为问题的复杂程度&#xff0c;E为解…

LabVIEW显微镜成像偏差校准

在高精度显微镜成像中&#xff0c;用户常常需要通过点击图像的不同位置&#xff0c;让电机驱动探针移动到指定点进行观察。然而&#xff0c;在实际操作中&#xff0c;经常会遇到一个问题&#xff1a;当点击位于图像中心附近的点时&#xff0c;探针能够相对准确地定位&#xff1…

【AI实践】deepseek支持升级git

当前Windows 11 WSL的git是2.17&#xff0c;Android Studio提示需要升级到2.19版本 网上找到指导文章 安装git 2.19.2 cd /usr/src wget https://www.kernel.org/pub/software/scm/git/git-2.19.2.tar.gz tar xzf git-2.19.2.tar.gz cd git-2.19.2 make prefix/usr/l…

在Windows 7操作系统,基于llama.cpp本地化部署 deepseek-r1模型的方法 2025-02-08

一、概述 现在已经是大模型时代。 个人认为&#xff0c;deepseek效果惊艳&#xff0c;大模型已进入实用阶段。 有些电脑&#xff0c;由于种种原因&#xff0c;还在用 Windows 7&#xff0c; Windows XP 等操作系统。 为了让这些电脑用上大模型&#xff0c;本教程在 llama.c…

消息中间件:RabbitMQ镜像集群部署配置全流程

目录 1、特点 2、RabbitMQ的消息传递模式 2.1、简单模式&#xff08;Simple Mode&#xff09; 2.2、工作队列模式&#xff08;Work Queue Mode&#xff09; 2.3、发布/订阅模式&#xff08;Publish/Subscribe Mode&#xff09; 2.4、路由模式&#xff08;Routing Mode&am…

【MySQL — 数据库基础】深入解析 MySQL 的联合查询

1. 插入查询结果 语法 insert into table_name1 select* from table_name2 where restrictions ;注意&#xff1a;查询的结果集合&#xff0c;列数 / 类型 / 顺序 要和 insert into 后面的表相匹配&#xff1b;列的名字不要求相同&#xff1b; create table student1(id int , …

算法学习笔记之数学基础

例1&#xff08;最小公倍数与最大公约数&#xff09; 计算最小公倍数 公式&#xff1a; LCM(A,B) A*B/GCD(A,B) A与B的最小公倍数等于A*B除以A与B的最大公约数 计算最大公约数&#xff1a;辗转相除法 原理&#xff1a;设A与B的最大公约数为x&#xff0c;则A是x的倍数&am…

通过操作系统中的IO模型理解Java中的BIO,NIO,AIO

操作系统中的三种IO模型 阻塞I/O 先来看看阻塞 I/O&#xff0c;当用户程序执行 read&#xff0c;线程会被阻塞 一直等到内核数据准备好&#xff0c;并把数据从内核缓冲区拷贝到应用程序的缓冲区中&#xff0c;当拷贝过程完成&#xff0c;read 才会返回 注意&#xff1a;阻塞…

多项式插值(数值计算方法)Matlab实现

多项式插值&#xff08;数值计算方法&#xff09;Matlab实现 一. 原理介绍二. 程序设计1. 构建矩阵2. 求解矩阵方程3. 作出多项式函数4. 绘制插值曲线5. 完整代码 三. 图例 一. 原理介绍 关于插值的定义及基本原理可以参照如下索引 插值原理&#xff08;数值计算方法&#xff…

SpringMVC请求执行流程源码解析

文章目录 0.SpringMVC九大内置组件1.processRequest方法1.请求先到service方法2.然后不管是get还是post都会跳转到processRequest方法统一处理 2.doService方法3.doDispatch方法1.代码2.checkMultipart 4.核心流程 0.SpringMVC九大内置组件 1.processRequest方法 1.请求先到se…

在vivado中对数据进行延时,时序对齐问题上的理清

在verilog的ISP处理流程中&#xff0c;在完成第一个模块的过程中&#xff0c;我经常感到困惑&#xff0c;到底是延时了多少个时钟&#xff1f;今日对这几个进行分类理解。 目录 1.输入信号激励源描述 1.1将数据延时[9]个clk 1.2将vtdc与hzdc延时[9]个clk(等价于单bit的数据…

Spring 项目接入 DeepSeek,分享两种超简单的方式!

⭐自荐一个非常不错的开源 Java 面试指南&#xff1a;JavaGuide &#xff08;Github 收获148k Star&#xff09;。这是我在大三开始准备秋招面试的时候创建的&#xff0c;目前已经持续维护 6 年多了&#xff0c;累计提交了 5600 commit &#xff0c;共有 550 多位贡献者共同参与…

蓝桥杯-洛谷刷题-day5(C++)(为未完成)

1.P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布 i.题目 ii.代码 #include <iostream> #include <string> using namespace std;int N, Na, Nb; //0-"剪刀", 1-"石头", 2-"布", 3-"蜥", 4-"斯"&#xff1…

MySQL - 索引 - 介绍

索引(Index)是帮助数据库高效获取数据的数据结构. 结构 语法 创建索引 creat [unique] index 索引名 on 表名 (字段名, ...); //创建唯一索引时加上unique, 多个字段用逗号隔开 查看索引 show index from 表名; 删除索引 drop index 索引名 on 表名;

2021年全国研究生数学建模竞赛华为杯E题信号干扰下的超宽带(UWB)精确定位问题求解全过程文档及程序

2021年全国研究生数学建模竞赛华为杯 E题 信号干扰下的超宽带(UWB)精确定位问题 原题再现&#xff1a; 一、背景   UWB&#xff08;Ultra-Wideband&#xff09;技术也被称之为“超宽带”&#xff0c;又称之为脉冲无线电技术。这是一种无需任何载波&#xff0c;通过发送纳秒…

安装WPS后,导致python调用Excel.Application异常,解决办法

在使用xlwings编辑excel文件时&#xff0c;默认调用的是“Excel.Application”&#xff0c;如果安装过wps&#xff0c;会导致该注册表为WPS&#xff0c;会导致xlwings执行异常 因为安装过WPS&#xff0c;导致与Excel不兼容的问题&#xff0c;想必大家都听说过。有些问题及时删…

STM32智能小车(循迹、跟随、避障、测速、蓝牙、wifi、4g、语音识别)总结

前言 有需要帮忙代做51和32小车或者其他单片机项目&#xff0c;课程设计&#xff0c;报告&#xff0c;PCB原理图的小伙伴&#xff0c;可以在文章最下方加我V交流咨询&#xff0c;本篇文章的小车所有功能实现的代码还有硬件清单放在资源包里&#xff0c;有需要的自行下载即可&a…

机器学习所需要的数学知识【01】

总览 导数 行列式 偏导数 概理论 凸优化-梯度下降 kkt条件

singleTaskAndroid的Activity启动模式知识点总结

一. 前提知识 1.1. 任务栈知识 二. Activity启动模式的学习 2.1 standard 2.2 singleTop 2.3.singleTask 2.4.singleInstance 引言&#xff1a; Activity作为四大组件之一&#xff0c;也可以说Activity是其中最重要的一个组件&#xff0c;其负责调节APP的视图&#xff…