首页 > 编程语言 >Qt实现多线程编程的两种方式

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

时间:2023-02-01 22:37:47浏览次数:60  
标签:parent include Qt thread void 编程 QWorker 多线程 MainWindow


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


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

代码示例:

#ifndef QDEMOTHREAD_H
#define QDEMOTHREAD_H

#include <QThread>
#include <QDebug>

class QDemoThread : public QThread
{
Q_OBJECT

public:
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(); // 启动线程
}
}

运行效果:

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


方式二: 创建一个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_OBJECT

public:
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(); // 不要指定parent
worker = new QWorker(); // 不要指定parent

// thread的finished和deleteLater相连接后,在thread退出时自动删除thread对象,无需手动delete thread
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
// thread的finished和worker的deleteLater相连接后,在thread退出时自动删除worker对象,无需手动delete worker
connect(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);
}

程序界面:

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

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

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


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


ends…


标签:parent,include,Qt,thread,void,编程,QWorker,多线程,MainWindow
From: https://blog.51cto.com/u_15950551/6031930

相关文章

  • 交叉编译并移植tslib-1.21和QT4.8.5运行第一个嵌入式Qt程序
    嵌入式linux平台交叉编译并移植QT4.8.5运行第一个嵌入式Qt程序开发环境:ubuntu1404-i686TQ2440开发板(samsungs3c2440)天嵌官方交叉编译器(版本4.3.3)qt-everywhere-opensourc......
  • Qt模型视图结构3_模型索引与模型的常用函数
    目录前言模型索引相关函数模型索引与模型访问和修改数据项的方法前言在数据项、模型以及视图三者之间,模型索引扮演着至关重要的角色。因此在此将模型索引的函数列举一下......
  • QTcpServer和QTcpSocket使用详解
    QTcpServer和QTcpSocket使用详解1、基本使用方法QTcpServer和QTcpSocket的使用是密不可分的,所以两者一块演示使用方法。QTcpServer常用信号:newConnection()信号,该信号用于处......
  • 专业精进之路:构建扎实而有实效的编程知识体系
    对世界上任何一件事物保持谦卑求知之心。在“打造适合自己的知识库”一文中,讲到了构建适合自己的知识库的一些经验和做法,不过,那还仅限于工具之法,并未涉及知识构建之法......
  • Qt设置应用程序图标、小图标显示+打包发布exe
    Qt设置应用程序图标、小图标显示+打包发布exe目录​​Qt设置应用程序图标、小图标显示+打包发布exe​​​​(一)设置应用程序图标、小图标​​​​(二)打包发布exe程序​​​​(......
  • PyQt5打包成exe可执行程序
    PyQt5打包成exe可执行程序安装打包程序:pipinstallpyInstaller打包命令格式:​​​pyinstaller[选项]文件名​​选项:-F,–onefile打包成一个单独的exe文件,类似于C语言的静......
  • Python网络编程—TCP客户端和服务器
    Python网络编程—TCP客户端和服务器客户端importsocket'''客户端创建步骤:1、创建网络套接字2、连接到目标IP地址和端口3、收发数据4、关闭套接字'''IP=socket.gethostnam......
  • Qt | 拖放、拖动的使用、将文件拖入使用示例
    Qt|拖放、拖动的使用、将文件拖入使用示例1、窗体的拖动Qt的控件本身支持了很强大拖放、拖动功能,对于窗体的拖动,例如QDialog,可以覆写这四个函数:voiddragEnterEvent(QDrag......
  • QTableView的样式设置和常用函数
    QTableView用于显示二维数据,常常与QStandardItemModel结合使用。目录样式设置表头样式设置表头样式设置注意事项表格样式设置常用函数model相关tableView相关headerView......
  • Qt | QDialogButtonBox使用示例
    Qt|QDialogButtonBox使用示例1、简介QDialogButtonBox类,该类包含很多按钮控件,在窗体(widget)或者对话框(dialog)有多个按钮的时候,为方便管理就可以使用该类成组进行管理。......