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

qt线程介绍

目录

介绍

 线程类 QThread

 方式1

方式2

案例

线程资源释放


介绍

qt为多线程提供了完美的支持,实现多线程一般是从从QTHread中继承定义自己的线程类,QT也提供了QMutexLocker,QwaitCondition等类实现线程同步,与Linux系统或C++中的线程库类似。这里简单介绍下多线程的创建。

  • 默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新
  • 子线程负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理
  • 主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号槽机制

 线程类 QThread

常用API:

[virtual protected] void QThread::run();

run()是一个虚函数,如果想让创建的子线程执行某个任务,需要写一个子类让其继承QThread,并且在子类中重写父类的run()方法,函数体就是对应的任务处理流程,当前线程对象调用槽函数start()启动子线程,当子线程被启动,这个run()函数也就在线程内部被调用了。

信号与槽函数:

// 线程中执行的任务完成了, 发出该信号
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();

[slot] void QThread::quit();


// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();

 方式1

创建一个线程类的子类,让其继承QT中的线程类 QThread,重写父类的 run() 方法,启动子线程, 调用 start() 方法。

举例:

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>
#include<QThread>class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = nullptr);
protected:void run();
signals:void curNumber(int num);
};#endif // MYTHREAD_H
#include "mythread.h"
#include<QDebug>
MyThread::MyThread(QObject *parent)
{
}void MyThread::run()
{qDebug() << "当前线程对象的地址: " << QThread::currentThread();int num = 0;while(1){emit curNumber(num++);//子线程每秒发出一次信号if(num == 10000000){break;}QThread::usleep(1);}qDebug() << "run() 执行完毕, 子线程退出...";}
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << "主线程对象地址:  " << QThread::currentThread();MyThread* m=new MyThread;connect(m, &MyThread::curNumber, this, [=](int num)//子线程每秒发出一次信号{ui->label->setNum(num);});connect(ui->pushButton, &QPushButton::clicked, this, [=](){// 启动子线程m ->start();});
}MainWindow::~MainWindow()
{delete ui;
}

方式2

  1. 创建一个新的类A,让这个类从QObject派生,这个类中添加一个公共的成员函数来处理对应的任务
  2. 在主线程中创建一个QThread对象
  3. 在主线程中创建工作的类对象A(不能指定父对象)
  4. 将对象A移动到创建的子线程对象中, 需要调用QObject类提供的moveToThread()方法
  5. 启动子线程,调用 start(), 这时候线程启动了, 但是移动到线程中的对象并没有工作
  6. 调用MyWork类对象的工作函数,让这个函数开始执行。

例如:

#ifndef WORK_H
#define WORK_H
#include <QObject>class Work : public QObject
{Q_OBJECT
public:explicit Work(QObject *parent = nullptr);void Working();
signals:void curNumber(int num);};
#endif // WORK_H
#include "work.h"
#include<QDebug>
#include<QThread>
Work::Work(QObject *parent): QObject{parent}
{
}void Work::Working()
{qDebug() << "当前线程对象的地址: " << QThread::currentThread();int num = 0;while(1){emit curNumber(num++);//子线程每秒发出一次信号if(num == 10000000){break;}QThread::usleep(1);}qDebug() << "run() 执行完毕, 子线程退出...";
}
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << "主线程对象地址:  " << QThread::currentThread();QThread* sub = new QThread;//创建线程对象Work* w=new Work;          //创建工作对象,该对象包含业务处理方法,不要指定给创建的对象指定父对象w->moveToThread(sub);    //将工作对象移动到子线程中sub->start();connect(ui->startBtn, &QPushButton::clicked, w,&Work::Working);// 显示数据connect(w, &Work::curNumber, this, [=](int num){ui->label->setNum(num);});
}

案例

在一个子线程程中随机生成1000个数,将这些数据交给另一个子线程去排序,后面将排序的结果返回给主线程,主线程再将数据输出到窗口中。

这里采用方案1进行演示:

生成随机数线程:

class Genera : public QThread //该类来生成随机数
{Q_OBJECT
public:explicit Genera(QObject *parent = nullptr);void getnum(int k);
protected:void run();//重写run方法,生成随机数
private:int num_;  //获取主线程传来的数据,这里为生成随机数的个数signals:void sendnum(QVector<int> v);//当随机数生成完后,发射该信号,将数据传给主线程和排序线程
};Genera::Genera(QObject *parent): QThread{parent}
{
}
void Genera::getnum(int k)
{num_=k;
}
void Genera::run()
{qDebug()<<"当前线程是"<<" "<<QThread::currentThread();QVector<int> v;QElapsedTimer q;q.start();for(int i=0;i<num_;i++){v.push_back(qrand()%10000);}int m=q.elapsed();qDebug()<<"生成随机的时间是"<<" "<<m;emit sendnum(v);}

排序线程:

class BubbleSort : public QThread //该类来生成随机数
{Q_OBJECT
public:explicit BubbleSort(QObject *parent = nullptr);void getnum(QVector<int>);//获取生成随机数线程传来的数据
protected:void run();//进行排序
private:QVector<int> v;signals:void Finish(QVector<int> v);//排序完成后发射该信号,将排序结果给主线程
};BubbleSort::BubbleSort(QObject *parent): QThread{parent}
{ 
}
void BubbleSort::getnum(QVector<int> list)
{v=list;
}
void BubbleSort::run()
{qDebug()<<"当前线程是"<<" "<<QThread::currentThread();QElapsedTimer q;q.start();for(int i=0;i<v.size();i++){for(int j=0;j<v.size()-i-1;j++){if(v[j]>v[j+1]){int tmp=v[j+1];v[j+1]=v[j];v[j]=tmp;}}}int m=q.elapsed();qDebug()<<"排序的时间是"<<" "<<m;emit Finish(v);
}

主线程:

class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
signals:void starting(int num);//生成随机数的个数private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_HMainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//创建子线程Genera * g=new Genera;//生成随机数BubbleSort* b=new BubbleSort;//排序connect(this,&MainWindow::starting,g,&Genera::getnum);//启动子线程connect(ui->pushButton,&QPushButton::clicked,this,[=](){emit starting(1000);//发射该信号,将生成随机数的个数传给子线程g->start();});connect(g,&Genera::sendnum,b,&BubbleSort::getnum);//排序线程接受生成随机数线程传来的数据//接受子线程传来的排序数connect(g,&Genera::sendnum,this,[=](QVector<int> v){//说明随机生成数已生成好b->start();for(int i=0;i<v.size();i++){ui->listWidget->addItem(QString::number(v.at(i)));}});connect(b,&BubbleSort::Finish,this,[=](QVector<int> v){for(int i=0;i<v.size();i++){ui->listWidget_2->addItem(QString::number(v.at(i)));}});
}MainWindow::~MainWindow()
{delete ui;
}

 结果:

线程资源释放

1.创建线程时,给它指明父对象,让其添加到对象树列表中。

2.手动释放,调用quit,wait,delete:例如,在上面的代码中,new出来的时局部变量:

 connect(this,&MainWindow::destroyed,this,[=](){g->quit();g->wait();g->deleteLater();//类似与c++中delete});

http://www.lryc.cn/news/180646.html

相关文章:

  • 记一次用dataframe进行数据清理
  • 《Jetpack Compose从入门到实战》 第二章 了解常用UI组件
  • Vue3 引入使用 vant组件详解
  • NOSQL Redis Ubuntu系列 常用的配置 及密码登录
  • C语言解析GPS源数据
  • 【论文阅读】(CVPR2023)用于半监督医学图像分割的双向复制粘贴
  • [Linux 基础] 一篇带你了解linux权限问题
  • FPGA project :HDMI
  • 基于微信小程序的物流快递信息查询平台同城急送小程序(亮点:寄件、发票申请、在线聊天)
  • idea插件推荐
  • Arcgis快速计算NDVI
  • SpringCloud Alibaba - 基于 FeignClient 整合 Sentinel,实现“线程隔离”和“熔断降级”
  • Acwing 906. 区间分组
  • 阿里云 Oss 权限控制
  • CSS详细基础(六)边框样式
  • 支持向量机SVM:从数学原理到实际应用
  • 【办公自动化】在Excel中按条件筛选数据并存入新的表(文末送书)
  • 第三章:最新版零基础学习 PYTHON 教程(第十一节 - Python 运算符—Python 中的any与all)
  • Pytorch单机多卡分布式训练
  • asp.net coremvc+efcore增删改查
  • Java基础面试,什么是面向对象,谈谈你对面向对象的理解
  • Ubuntu系统初始设置
  • 焕新古文化传承之路,AI为古彝文识别赋能
  • 毛玻璃动画交互效果
  • Audio2Face的工作原理
  • 【面试题】2023前端面试真题之JS篇
  • Mysql 分布式序列算法
  • Windows/Linux双系统卸载Ubuntu
  • asp.net core mvc 视图组件viewComponents
  • 如何保持终身学习