alin的学习之路:Qt与多线程

如果程序在进行复杂的逻辑处理过程中, 对窗口进行操作, 就会出现无响应的情况。

如何解决这样的问题与高并发的问题?

需要使用多线程。

方式1

特点:简单

  1. 创建一个自定义的类,先选择继承QObject,随后改为继承QThread

  2. 重写父类的run()方法,在run()方法里面写子线程的执行逻辑。注意run函数是protected的作用域

    [virtual protected] void QThread::run()
    
  3. 在主线程中创建子线程的对象

  4. 使用子线程对象调用start()方法,即开始执行子线程的逻辑

    [slot] void QThread::start(Priority priority = InheritPriority)
    不能在类的外部调用run() 方法启动子线程, 在外部调用start()相当于让run()开始运行
    

线程间通信:

子线程类定义一个槽函数,将需要通信的数据放在信号函数的参数中,在子线程的run()方法中触发信号。

注意事项: 在Qt中在子线程中不要操作程序中的窗口类型对象, 不允许, 如果操作了程序就挂了,只有主线程才能操作程序中的窗口对象, 默认的线程就是主线程, 自己创建的就是子线程

demo

mythread.h

#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);public slots:
};#endif // MYTHREAD_H

mythread.cpp

#include "mythread.h"MyThread::MyThread(QObject *parent) : QThread(parent)
{}void MyThread::run()
{int num = 0;for(int i=0; i<10000000; ++i){emit curNumber(num++);usleep(1);}
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
#include <QThread>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);MyThread* mythread = new MyThread;connect(ui->pushButton, &QPushButton::clicked, this, [=](){mythread->start();});connect(mythread, &MyThread::curNumber, this, [=](int num){ui->label->setNum(num);});
}MainWindow::~MainWindow()
{delete ui;
}

方式2

特点:灵活

  1. 创建一个工作类,定义一个工作函数,这个工作函数就是子线程的执行代码。
  2. 主线程中创建一个工作类的对象
    • 千万不要指定给创建的对象指定父对象
  3. 主线程中创建一个QThread类的对象
  4. 将工作类对象移动到创建的线程对象中,使用QObject类提供的api, moveToThread
    • void QObject::moveToThread(QThread *targetThread);
    • work->moveToThread(sub); // 移动到子线程中工作
  5. 启动子线程,调用线程对象中的start()方法,此时并没有开始执行子线程的代码逻辑
  6. 调用工作对象的工作函数,此时子线程开始执行

线程间通信:

需要使用槽函数

demo

mywork.h

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

mywork.cpp

#include "mywork.h"
#include <QDebug>MyWork::MyWork(QObject *parent) : QObject(parent)
{}void MyWork::doWork()
{int num = 0;qDebug() << "当前线程为:" << QThread::currentThread();for(int i=0; i<10000000; ++i){emit curNumber(num++);QThread::usleep(1);}qDebug() << "run() 执行完毕, 子线程退出...";
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mywork.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);//创建一个QThread对象QThread *sub = new QThread;//创建工作对象 --> 注意不能在构造函数中指定自己的parentMyWork* mywork = new MyWork;//将工作对象移动到线程对象中mywork->moveToThread(sub);//使用线程对象调用start方法,但是此时并没有开始执行子线程的逻辑,需要调用工作函数中的对应函数才可以sub->start();connect(ui->pushButton, &QPushButton::clicked, mywork, &MyWork::doWork);connect(mywork, &MyWork::curNumber, this, [=](int num){ui->label->setNum(num);});}MainWindow::~MainWindow()
{delete ui;
}

alin的学习之路:Qt与多线程相关推荐

  1. alin的学习之路:在Qt中使用Oracle数据库

    alin的学习之路:在Qt中使用Oracle数据库 1. 准备工作 在Qt中安装好Source插件,将其中的oci模块进行编译,注意要在oci.pro中指定数据块的动态库和头文件路径 需要在Qt项目文 ...

  2. alin的学习之路:共享内存

    alin的学习之路:共享内存 1. 概念 共享内存是进程间通信中效率最高的一种方式. 共享内存: 可以被多个进程同时使用的一块内核的内存 有血缘关系的进程 没有血缘关系的进程 这块内存不属于任何的进程 ...

  3. alin的学习之路:序列化与protobuf

    alin的学习之路:序列化与protobuf 1. 序列化(串行化) 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程,与之相对应的过程称之为反序列化(Unser ...

  4. alin的学习之路(Linux网络编程:十)(http协议,BS模型)

    alin的学习之路(Linux网络编程:十)(http协议,BS模型) 需求:使用B/S模型来访问主机中的文件(包括目录) 0. B/S 模型 注意事项 1. 浏览器请求ico ​ 准备一个favic ...

  5. alin的学习之路:c++11特性

    alin的学习之路:c++11 新特性 参考链接:https://blog.csdn.net/zzb2019/article/details/81624367 1. 关键字新增 auto declty ...

  6. alin的学习之路:面试题 计算机网络相关

    alin的学习之路:面试题 计算机网络相关 介绍下proactor和reactor reactor:同步IO proactor:异步IO Reactor框架中用户定义的操作是在实际操作之前调用的.比如 ...

  7. alin的学习之路:面试题 数据库相关

    alin的学习之路:面试题 数据库相关 如何提高查询速度? 使用索引 create index 索引名 on 表名(列名1,列名2,--); 数据库索引,事务,事务级别 使用索引可以提高查询效率 事务 ...

  8. alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组)

    alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组) 1. SQL语句 1.1 sql语言类型 sql是一门独立的 ...

  9. alin的学习之路:加密相关知识(加密和解密,常见加密算法,消息验证码HMAC,数字签名)

    alin的学习之路:加密相关知识(加密和解密,常见加密算法,消息验证码HMAC,数字签名) 1. 加密和解密 1.1 加密的三要素 原始数据 加密操作: 明文 -> 密文 解密操作: 密文 -& ...

最新文章

  1. Android Studio ndk-Jni开发详细
  2. 元宇宙iwemeta: 北交所开创,资本市场服务创新型中小企业掀开新篇章,上市企业小盘点
  3. matlab dmodce,吧里有没有大神可以教我怎么改dmodce函数,用的matlab2012a版本
  4. VTK:场景边界SceneBounds用法实战
  5. jvm类加载器以及双亲委派
  6. oracle 群集 无存储,存储的群集注意事项 - Oracle® ZFS Storage Appliance 管理指南
  7. HUT-XXXX 数学
  8. windows2008下运行环境部署(iis,ftp,oracle)
  9. 优秀流程图和逻辑图画法的分析和借鉴
  10. springboot项目在服务器怎么启动,springboot在服务器上启动的几种方式,亲测通过!...
  11. 高通QPST Download使用方法
  12. 机器学习-周志华总结
  13. PAT-Head of Hangs
  14. Service Mesh初识
  15. fedora28/29/32/centos ipmi 登录解决
  16. 一个程序员的学习历程
  17. 叮咚!您有蜡笔射手等五个新的软件,请注意查收哦
  18. 英语语法——特殊结构
  19. 【制作多媒体演示文稿软件】Focusky教程 | 轻松制作毕业答辩演示文稿
  20. 计算机实训实验报告,计算机实训实验报告.doc

热门文章

  1. PLSQL查询语句中日期格式使用不当会导致性能和效率很低
  2. 使用electron-builder --win --x64 命令 app-builder-bin\win\x64\app-builder.exe 报错
  3. Linux Socket编程入门——浅显易懂
  4. 浅显理解Java泛型的super和extends
  5. html个人网页步骤,个人网页制作的流程和步骤
  6. 如何使用 Google 的 AutoAugment 改进图像分类器
  7. 中国电子学会和nct哪个证书好,适合报名哪一个呢?
  8. 第4天:C语言与画面显示的练习
  9. ❤️‍Spring从入门到大神--事务管理(搞笑漫画讲解!简单易懂!!)
  10. 昆仑linux软件著作权,基于开源软件著作权