Qt实现多线程编程的两种方式


方式一: 继承自QThread类,覆写run函数。此实现方法只有run函数内的代码是运行在子线程内。

代码示例:

#ifndef QDEMOTHREAD_H
#define QDEMOTHREAD_H#include <QThread>
#include <QDebug>class QDemoThread : public QThread
{Q_OBJECTpublic:QDemoThread(QObject* parent = nullptr);~QDemoThread();protected:void run() override;public:void stop();private:bool flag;
};#endif // QDEMOTHREAD_H
#include "qdemothread.h"QDemoThread::QDemoThread(QObject* parent) : QThread(parent)
{}QDemoThread::~QDemoThread()
{}void QDemoThread::run()
{flag = true;while(flag){qDebug() << "thread id:" << QThread::currentThreadId();sleep(1);}
}void QDemoThread::stop()
{flag = false;if(isRunning()){exit();  // 结束线程wait();  // 等待退出}
}

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);demoThread = new QDemoThread(this);qDebug() << "main thread id:" << QThread::currentThreadId();
}Widget::~Widget()
{demoThread->stop();  // 退出线程delete ui;
}void Widget::on_pushButton_clicked()
{if(!demoThread->isRunning()){demoThread->start();  // 启动线程}
}

运行效果:


方式二: 创建一个QThread和QWorker(继承自QObject)类对象,使用moveToThread函数移动到thread中运行,通过thread类start信号和worker的init槽函数绑定,init槽函数内是一些初始化操作,然后定义个定时器,周期触发doWork()。

网上有很多教程是在doWork()中使用while(isRunning)死循环的形式,不建议这么干,如果线程一直在doWork中死循环,那么他是无法接收到来自外部的信号的。推荐的方法是用定时器周期触发。

示例代码:

QWorker类:

#ifndef QWORKER_H
#define QWORKER_H#include <QObject>
#include <QThread>
#include <QDebug>class QWorker : public QObject
{Q_OBJECT
public:explicit QWorker(QObject *parent = nullptr);~QWorker();signals:void newData(QByteArray data);    // 将本类内的私有数据通过该信号发射出去,供外部使用public slots:void init();         // 一些必要的初始化操作写在此函数内void doWork();       // 一些耗时操作写在此函数内void writeData(const char* buf, qint64 len);  // 供外部使用的操作接口
};#endif // QWORKER_H
#include "qworker.h"QWorker::QWorker(QObject *parent) : QObject(parent)
{qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}QWorker::~QWorker()
{qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}void QWorker::init()
{qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();
}void QWorker::doWork()
{static int count = 0;qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId() << ">>>" << count++;
}void QWorker::writeData(const char* buf, qint64 len)
{qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId() << ">>>" << QByteArray(buf, len);
}

主线程:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "qworker.h"
#include <QTimer>namespace Ui {class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();private:Ui::MainWindow *ui;QWorker* worker;QThread* thread;QTimer* timer;signals:void writeData(const char* buf, qint64 len);void stopWork();
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();timer = new QTimer(this);thread = new QThread();  // 不要指定parentworker = new QWorker();  // 不要指定parent// thread的finished和deleteLater相连接后,在thread退出时自动删除thread对象,无需手动delete threadconnect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); // thread的finished和worker的deleteLater相连接后,在thread退出时自动删除worker对象,无需手动delete workerconnect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));connect(thread, SIGNAL(started()), worker, SLOT(init()));connect(timer, SIGNAL(timeout()), worker, SLOT(doWork()));connect(this, SIGNAL(writeData(const char*,qint64)), worker, SLOT(writeData(const char*,qint64)));worker->moveToThread(thread);thread->start();timer->start(1000);  // 1000ms执行一次doWork()
}MainWindow::~MainWindow()
{if(timer->isActive()){timer->stop();}if(thread->isRunning()){thread->quit();thread->wait();}qDebug() << __FUNCTION__ << "Thread ID:" << QThread::currentThreadId();delete ui;
}void MainWindow::on_pushButton_clicked()
{emit writeData("hello world\r\n", 13);
}

程序界面:

运行后控制台打印信息如下:

可以看到的是,MainWindow和QWorker的构造函数中都显示线程ID为0x336c,而在QWorker的析构函数中显示线程ID为0x22a8,这说明moveToThread确实将worker移动到了thread中;而且还可以看到的是,QWorker的槽函数init、doWork、writeData也都是运行在了子线程中!


ends…

Qt实现多线程编程的两种方式相关推荐

  1. 实现Windows下Qt扫描U盘的两种方式

    参考网上资源,总结了如下实现Windows下Qt扫描U盘的两种方式:. 方式1: 检测Windows的事件–WM_DEVICECHANGE 缺点:想要检测时,必须发生过一次U盘插拔动作,需要手动&qu ...

  2. python: 多线程实现的两种方式及让多条命令并发执行

    一 概念介绍 Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法:另一种是创建一个threading. ...

  3. python 并发执行命令_python: 多线程实现的两种方式及让多条命令并发执行

    一 概念介绍 Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法:另一种是创建一个threading. ...

  4. 多线程实现的两种方式及其区别

    继承Thread public class Demo2_Thread {public static void main(String[] args) {MyThread mt = new MyThre ...

  5. java 多线程两种方式_JAVA多线程实现的两种方式

    java多线程实现方式主要有两种:继承Thread类.实现Runnable接口 1.继承Thread类实现多线程 继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了 ...

  6. Java多线程实现的两种方式

    Java多线程实现方式:1.实现Runnable接口2.继承Thread类,虽然是比较基础的知识点,作为学习记录写下来,高手略过! 1.实现Runnable接口 1) RunnableDemo类 pa ...

  7. 【大数据开发】SparkCore——Spark作业执行流程、RDD编程的两种方式、简单算子

    文章目录 一.Spark作业执行流程(重点) 二.RDD编程 2.1创建RDD的⼆种⽅式: 2.2Transformation算⼦ 2.3Action算子 三.简单算子(必须掌握) 3.1 map.m ...

  8. Qt 按键触发事件的两种方式

    方式1.传统connect()函数 例如: connect(ui->findPushBtn,SIGNAL(clicked()),this,SLOT(find())); 参数1:事件UI发送者 参 ...

  9. 23.多线程 实现的两种方式

    2019独角兽企业重金招聘Python工程师标准>>> 方式一:继承 Thread 接口 1. 效果 2.代码 继承Thread类的类代码 package cn.ma.thread0 ...

最新文章

  1. Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面
  2. linux下电池测试软件,你们要的App电量分析测试来了
  3. Sitecore 个性化 - 近距离和过于个人化?
  4. 推荐一个Chrome扩展应用,能够自动去除CSDN广告
  5. 6月24 面向对象的设计原则-----工厂模式和单列模式
  6. LINUX矩阵键盘简单介绍,stm32矩阵键盘原理图及程序介绍
  7. 结合CmakeList来更好地理解windows下的动态库和静态库
  8. Java开发工具(Eclipse工作空间的基本配置)
  9. 2014年度总结——程序员生涯的开启
  10. PHP7.1 狐教程
  11. C#实现图片转字符画
  12. 旋律生成算法的现状与挑战
  13. CSS编写格式边框与渐变内容补充
  14. 元宇宙的第一步,应该在汽车里迈出去?
  15. 【cs230】吴恩达Deep Learning-3/3
  16. WebAssembly 实践:如何写代码
  17. AcWing 1022 宠物小精灵之收服
  18. Java————错误:找不到或无法加载主类
  19. 一切照旧... ...
  20. Arduino超声波传感器使用

热门文章

  1. 为什么我不看好婚礼直播市场
  2. 英特尔和AMD联手对抗英伟达,共同研发人工智能芯片
  3. 无人机直播推流持续发力,联合EasyDSS为仓储物流业保驾护航
  4. 端口扫描工具 Nmap(一)
  5. Linux quota
  6. 同盾技术赋能“三河企业金服平台”正式上线
  7. Python 求阶乘
  8. Java爬取行政区域信息到数据库
  9. C# - partial 关键字
  10. 小米十周年,雷军做了一场 4 小时的走心演讲(实录)