C++及QT的线程学习

目录

一. 线程学习

二. 学习线程当中,得到的未知。

1. 了解以下MainWindow和main的关系

2. [=]()匿名函数 有函数体,没有函数名.

3. join和detach都是用来管理线程的生命周期的,它们的区别在于线程结束和资源的回收。

4. operator()() 仿函数

5. try-catch的使用以及细节。处理异常,try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。

6. C++创建多线程

1).普通函数的多线程创建方式

2).lsmbda表达式方式创建多线程

3).仿函数方式创建多线程

4).类成员函数创建多线程


一. 线程学习

首先,我们任意建一个QT工程,按下按键让数字递增。

void Widget::on_pushButton_clicked()
{
    int i = 0;
    for(;;)
    {
        ui->lcdNumber->display(QString::number(i++));
        sleep(1);
    }
}

但是我们在槽里这样写的话,移动窗口或者按下按键会报错,因为我们既要绘制窗口,又要响应窗口移动的操作,还要执行自加的逻辑,当执行到这个自加的逻辑就已经很忙了,它就没有功夫去调用显示逻辑了。我们可以加一个Debug查看一下。

void Widget::on_pushButton_clicked()
{
    int i = 0;
    for(;;)
    {
        qDebug() << i;
        ui->lcdNumber->display(QString::number(i++));
        sleep(1);
    }
}

可以发现操作台是有数在走的,但是却没有显示。

这时候我们就得采用多线程。那么我们使用join还是detach呢,因为主线程也要执行,不可能等待子线程执行,而且主线程本身就是一个循环,比如return a.exec();主进程不会退出,所以使用detach。

void Widget::on_pushButton_clicked()
{
    std::thread my_thread(&Widget::showInfo,this);
    my_thread.detach();
}

void Widget::showInfo()
{
    int i = 0;
    for(;;)
    {
        qDebug() << i;
        ui->lcdNumber->display(QString::number(i++));
        sleep(1);
    }
}

因为是在栈中定义的my_thread,所以不需要担心资源回收的问题,函数一结束,my_thread就销毁了,不用担心线程回收的问题。

这样,我们点击按钮开始计数之后就不会卡死。

当然QT中封装了一个多线程的类,叫QThread。刚刚我们写的线程是没有退出的逻辑的,所以接下来我们使用QThread。

定义一个自定义的类,继承QThread并重写run()方法,在里面写线程执行的逻辑,定义一个信号。

#include "my_thrad.h"
#include <QDebug>
My_Thrad::My_Thrad(QObject *parent) : QThread(parent)
{

}

void My_Thrad::run()
{
    int i = 0;
    for(;;)
    {
        qDebug() << i;
        emit threadSignal(i++);
        this->sleep(1);
        if (i > 10)
        {
            break;
        }
    }
}
#ifndef MY_THRAD_H
#define MY_THRAD_H

#include <QThread>
#include <QDebug>
class My_Thrad : public QThread
{
    Q_OBJECT
public:
    explicit My_Thrad(QObject *parent = nullptr);
    ~My_Thrad()//析构函数
    {
        qDebug() << "线程退出了,并回收了线程空间";
    }
protected:
    void run() override;
signals:
    void threadSignal(int val);
};

#endif // MY_THRAD_H

这里我们添加了一个析构函数,是判断新建线程能不能结束,而要保证关闭窗口的时候,线程仍然能够执行,实现一个安全可靠的退出,我们就要:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    my_thread = new My_Thrad(this);//this父对象就是main.cpp中的w
    connect(my_thread,&My_Thrad::threadSignal,[=](int val){
        ui->lcdNumber->display(QString::number(val));
    });
}

Widget::~Widget()
{
    delete ui;
    my_thread->exit();
    my_thread->wait();//等待线程执行完毕,然后才退出
    delete my_thread;
//   // my_thread->deleteLater();//它是依赖于某个对象,还依赖于主事件循环存在的情况下,才是有效的,所以这样会内存泄露
}

void Widget::on_pushButton_clicked()
{
    my_thread->start();//使用start间接调用的run方法
}

因此我们在~Widget()析构函数中写上述代码,实现等待线程执行完毕,才退出,并删除my_thread,输出”线程退出了,并回收了线程空间。

二. 学习线程当中,得到的未知。

1. 了解以下MainWindow和main的关系

main()函数,非窗体程序入口函数

Mainwindow函数,是窗体程序的入口函数

2. [=]()匿名函数 有函数体,没有函数名.

3. join和detach都是用来管理线程的生命周期的,它们的区别在于线程结束和资源的回收。

join函数会阻塞当前线程,直到被调用join()的线程(子线程)执行完毕并退出,在这个过程中,调用join()的线程会一直等待,直到被等待的线程退出。如果没有调用join函数。被等待的线程退出后,它的资源不会被回收,这可能会导致内存泄漏。

有时候我们不知道是否已经join()系统提供了一个joinable()来判断是否已经join()

使用detach会让线程在后台运行,这就意味着与主线程不能直接交互了,分离后的线程不能join

但使用detach时,要注意主进程运行的时间,不然可能线程还没执行完,主进程就结束了

4. operator()() 仿函数

5. try-catch的使用以及细节。处理异常,try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。

try{
//可疑代码
//将异常生成对象的异常对象传递给catch块
}catch(异常){
//对异常进行处理
}finally{
} //可以没有finally

6. C++创建多线程

1).普通函数的多线程创建方式

#include <thread>
#include <iostream>
#include <unistd.h>
#include <string>
using namespace std;
void showInfo()
{
    int i = 0;
    for(;;)
    {
        cout << i++ << endl;
        sleep(10000);
    }
}

void print(const string &s)
{
    cout<<"hello thread!"<<endl;
    cout<<s<<endl;
}

int main()
{
    /*
    thread my_thread(&showInfo);
    my_thread.join();
    my_thread.detach();
    */
    cout<<"main thread begin!"<< endl;
    string s = "hello world";
    thread t(&print,s);

    //thread t(&print);

    t.join();
    cout<<"main thread end!"<<endl;
    return 0;
}

2).lsmbda表达式方式创建多线程

#include <iostream>
#include <thread>
#include <string>
using namespace std;

int main()
{
    cout<<"main begin"<<endl;
    thread t(
        [](string s)-> void{
            cout<<"hello world!"<<endl;
            cout<<s<<endl;
        },
        "abc"
        );
    t.join();
    cout<<"main end"<<endl;
    return 0;
}

3).仿函数方式创建多线程

#include <iostream>
#include <thread>
#include <string>
using namespace std;
class MyThread{
public:
    void operator()()
    {
        cout<<"Hello World!"<<endl;
    }
};

int main()
{
    cout<<"main begin"<<endl;
    MyThread mt;
    thread t(mt);

    t.join();
    cout<<"main end"<<endl;

    return 0;
}

4).类成员函数创建多线程

#include <iostream>
#include <thread>
#include <string>
using namespace std;
class MyThread{
public:
    void print(const string &s)
    {
        cout<<"Hello World!"<<endl;
        cout<<s<<endl;
    }
};

int main()
{
    cout<<"main begin"<<endl;
    MyThread mt;
    thread t(&MyThread::print,&mt,"ac") ;

    t.join();
    cout<<"main end"<<endl;

    return 0;
}

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

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

相关文章

论文略读:OpenGraph: Towards Open Graph Foundation Models

arxiv 2023 1 intro Graph大模型希望OpenGraph能够捕捉通用的拓扑结构模式&#xff0c;对测试数据进行Zero-shot预测 仅通过前向传播过程&#xff0c;就可以对测试图数据进行高效的特征提取和准确预测模型的训练过程在完全不同的图数据上进行&#xff0c;在训练阶段不接触测试…

CSS3新增特性(一)

目录 一、CSS3 新增选择器 1. 子级选择器 2. 兄弟选择器 相邻兄弟选择器 其他兄弟选择器 3. 结构伪类选择器 ① E:first-child ② E:last-child ③ nth-child&#xff08;n&#xff09; n为数字&#xff1a; n为关键字&#xff1a; n为公式&#xff1a; ④ E: firs…

visionTransformer window平台下报错

错误&#xff1a; KeyError: Transformer/encoderblock_0/MlpBlock_3/Dense_0kernel is not a file in the archive解决方法&#xff1a; 修改这个函数即可&#xff0c;主要原因是Linux系统与window系统路径分隔符不一样导致 def load_from(self, weights, n_block):ROOT f&…

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试

【RT-Thread应用笔记】FRDM-MCXN947上的RW007实践——WiFi延迟和带宽测试 一、背景介绍1.1 RW007模组简介1.2 Arduino接口简介1.3 RW007软件包简介1.4 RT-Thread env工具简介 二、创建工程2.1 新建工程2.2 添加rw007软件包2.3 打开RW007配置项2.4 启用pin驱动2.5 禁用rw007的ST…

Cloud微服务:Ribbon负载均衡

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Ribbon负载均衡 一、Ribbon - 负载均衡原理、流…

探索 虚拟化技术+Docker部署与操作

目录 一、你知道哪些云 1.1国内云 1.2国外云 二、Iaas、 Paas、SaaS三种云服务区别 2.1第一层叫做IaaS 2.2第二层就是所谓的PaaS 2.3第三层也就是所谓SaaS 三、虚拟化架构 3.1寄居架构 3.2源生架构 3.3操作系统虚拟化架构 3.4混合虚拟化架构 四、虚拟化特点及优势…

jmeter5.4.1源码编译(IDEA)问题解决

问题现象&#xff1a;最近想更深入的研究下jmeter5.4.1的原理及功能具体实现&#xff0c;从官网down了个源码&#xff0c;在本地使用IDEA工具导入项目、编译时&#xff0c;报以下错误&#xff1a; class jdk.internal.loader.ClassLoaders$PlatformClassLoader cannot be cast…

vue整合Echarts

首先打开网址https://echarts.apache.org/examples/zh/index.html 进入Echars官网找到自己想要的图形我这里选择的是柱形图 点开完整代码直接cv大法 下载Echars的npm npm install echarts 在vue里面挂在个div 导入相关包 写个方法 就是cv过来的 然后改成后端传过来的值…

【STM32+HAL+Proteus】系列学习教程---RS485总线(收发仿真实现)

实现目标 1、掌握UART/USART/RS485等几个常见概念的区别 2、掌握RS485的逻辑电平、硬件接线等基础知识 3、具体实现目标&#xff1a;1、利用两个单片机组成RS485通信网络&#xff1b;2、两个单片机之间能实现正常收发数据。 一、串口、RS485等之间的关系 串口&#xff1a;是…

微机原理实验三、将AX寄存器中的16位数分成4组,每组4位,让后把这四组数分别放在AL,BL,CL,DL

微机原理实验三、将AX寄存器中的16位数分成4组&#xff0c;每组4位&#xff0c;让后把这四组数分别放在AL,BL,CL,DL 功能&#xff1a; 将AX寄存器中的16位数分成4组&#xff0c;每组4位&#xff0c;让后把这四组数分别放在AL,BL,CL,DL ; 调试结果&#xff1a; input&#xff1a…

ASP.NET集成客户关系管理的企业网站的设计与开发

摘 要 企业要在激烈的市场竞争中立于不败之地&#xff0c;就必须找一种全新的管理理念和管理手段&#xff0c;对其内部和外部资源进行有效的整合。新一代ERP产品正在向客户端和供应端延伸&#xff0c;客户端的延伸即是客户关系管理。对于每个企业来说客户管理的完善程度将直接…

计算机网络 --- WebSocket协议 和 Signalr

计算机网络 --- WebSocket协议 和 Signalr 什么是WebSocket什么是SignalrSignalr Example -- SimpleChat 什么是WebSocket HTTP是基于TCP协议的&#xff0c;同一时间里&#xff0c;客户端和服务器只能有一方主动发数据&#xff0c;是半双工通信。 通常&#xff0c;打开某个网页…

Qt笔记-解决子控制大小获取不正确(width和height)需要重制窗体后,才能获得正确的值

在Qt中&#xff0c;子控件的宽度和高度在构造后并不准确&#xff0c;而只有在调整窗口大小后才正确&#xff0c;这可能是因为子控件的布局或者约束尚未完全计算和应用。 为了解决这个问题&#xff0c;可以使用QTimer来延迟获取子控件的宽度和高度&#xff0c;以确保在布局和约…

ffmpeg初体验

一&#xff1a;安装 sudo yum install epel-release -y sudo yum update -ysudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpmyum -y install …

数据结构(邓俊辉)学习笔记——向量vector_02_动态空间管理

文章目录 1. 概述2. 静态空间管理缺点3. 动态空间管理3.1 扩容3.1.1 如何实现扩容3.1.2 扩容算法3.1.3 容量递增策略 VS 容量倍增策略3.1.3.1 容量倍增策略分摊分析3.1.3.2 容量递增策略分摊分析3.1.3.3 结果对比 3.2缩容3.2.1 动态缩容算法实现3.2.2 动态缩容算法时间复杂度 4…

Opencv_3_图像对象的创建与赋值

ColorInvert.h 如下&#xff1a; #include <opencv.hpp> using namespace std; #include <opencv.hpp> using namespace cv; using namespace std; class ColorInvert{ public : void mat_creation(); }; ColorInvert.cpp 文件如下&#xff1a; #include &q…

自动驾驶---OpenSpace之Hybrid A*规划算法

1 背景 笔者在上周发布的博客《自动驾驶---低速场景之记忆泊车》中&#xff0c;大体介绍了记忆泊车中的整体方案&#xff0c;其中详细阐述了planning模块的内容&#xff0c;全局规划及局部规划&#xff08;会车&#xff09;等内容&#xff0c;包括使用的算法&#xff0c;但是没…

3D Gaussian Splatting介绍

目录 一、概述二、基础介绍1. 多维高斯分布2. 将3D 高斯投影到2D像素平面3. 球谐函数4. Splatting and α \alpha α blending 三、整体流程四、 伪代码五、评价指标六、实验结果七、reference 一、概述 3D Gaussian Splatting和NeRF一样&#xff0c;主要用于新视图合成。 特…

开源博客项目Blog .NET Core源码学习(17:App.Hosting项目结构分析-5)

本文学习并分析App.Hosting项目中前台页面的作品展示页面和首页页面。 作品展示页面 作品展示页面总体上为上下布局&#xff0c;上方显示导航菜单&#xff0c;下方从左向右显示图片数据&#xff0c;支持放大查看图片和下载图片。整个页面使用了layui中的面包屑导航、弹出层、流…

高通发布电脑CPU,比英特尔Ultra9领先51%

要说2024年最热门的关键词&#xff0c;那肯定非 AI 莫属&#xff0c;当前 AI 已经开始深入各行各业&#xff0c;AI 电视、AI 手机、AI 车机、AI 家电&#xff0c;以及 AI PC ,这些都意味着 AI 将对各个行业带来的新风向和不小的冲击。 2024 年了&#xff0c;PC 处理器还能卷出什…