首页 > 其他分享 >Qt 中的多线程 :重写 run 函数

Qt 中的多线程 :重写 run 函数

时间:2023-12-24 23:14:10浏览次数:40  
标签:run Qt QThreadTest 线程 WorkThread 多线程 QThread 函数

Qt 中的多线程主要是为了防止复杂耗时的操作阻塞主线程,导致界面卡死的问题。可以通过继承 QThread 类后,重写 run() 函数来实现。

一、 定义继承自 QThread 的类

定义一个类继承自 QThread,并重写虚函数 run(),将耗时的操作放在 run()函数中,然后在主线程中来通过调用该类的 start() 函数,从而实现启动子线程执行 run()函数中的内容。

1、 定义继承自 QThreadWorkThread ,作为子线程

WorkThread.h 内容如下:

#pragma once
#include <QThread>

/// <summary>
/// 通过继承 QThread类,并重写 run 函数来实现多线程操作,
/// 将复杂的操作放在run函数里面,run()函数相当于运行在一个新的线程中。
/// 需要公有继承 QThread 类,否则后面无法调用重载的 run 函数
/// </summary>
class WorkThread: public QThread
{
    Q_OBJECT

public:
    WorkThread();
    ~WorkThread();

    /**
    * @brief  在该函数中实现耗时阻塞主线程的操作,该函数中的操作将会在子线程中执行
    */
    void run() override;

signals:

    /**
     * 子线程无法直接操作UI,因此只能通过信号槽的机制来向主线程发送信号,
     * 主线程接受到该信号后,进行更新UI内容,从而实现间接操作UI.
     */
    void SendMsg(QString msg);
};


WorkThread.cpp 内容如下:

#include "WorkThread.h"

WorkThread::WorkThread()
{

}

WorkThread::~WorkThread()
{
    // 使用quit()或者exit()使得子线程能够退出消息循环,而不会一直阻塞在子线程中
    this->quit();

    // 等待子线程退出后,回收子线程的资源
    this->wait();
}

void WorkThread::run()
{
    int curId = (int)QThread::currentThreadId();

    emit SendMsg(QString("子线程id = %1").arg(curId));

    emit SendMsg("Start do something ...");

    QThread::sleep(10);

    QString resStr = "Finish complex operation";

    emit SendMsg(resStr);

    // 子线程中的消息循环函数,如果没有该函数,则子线程执行完后会立即退出
    // this->exec();
}

2、在主线程中调用子线程

QThreadTest.h 内容如下:

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QThreadTest.h"

#include "WorkThread.h"

class QThreadTest : public QMainWindow
{
    Q_OBJECT

public:
    QThreadTest(QWidget *parent = Q_NULLPTR);
    ~QThreadTest();

private slots:
    /**
     * 直接在主线程中进行耗时操作,会直接阻塞主UI线程,导致程序卡死.
     */
    void OnBtn01Clicked();

    /**
    * @brief  将创建一个线程来执行复杂的操作,避免阻塞UI线程。
    *         该类继承自 QThread,将复杂的操作写在 run()中,
    *         run()函数中的内容才会在子线程中执行。
    */
    void OnBtn02Clicked();

    /**
    * @brief  由于子线程不能直接操作UI,所以该函数用于将接受到的子线程内容显示在UI上
    * @param  [in]  msg
    */
    void GetResult(QString msg);

private:
    Ui::QThreadTestClass ui;

    WorkThread* workThread;  // 子线程的对象指针
};

QThreadTest.cpp 内容如下:

#include "QThreadTest.h"
#include <QPushButton>

QThreadTest::QThreadTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    // 在构造函数中初始化子线程的对象指针
    workThread = new WorkThread();

    // 子线程只能通过信号槽来间接的修改UI的内容
    connect(workThread, &WorkThread::SendMsg, this, &QThreadTest::GetResult);

    // 子线程结束之后释放其所占用的资源
    connect(workThread, &WorkThread::finished, workThread, &WorkThread::deleteLater);


    connect(ui.btn01, &QPushButton::clicked, this, &QThreadTest::OnBtn01Clicked);
    connect(ui.btn02, &QPushButton::clicked, this, &QThreadTest::OnBtn02Clicked);
}

QThreadTest::~QThreadTest()
{
}

void QThreadTest::OnBtn01Clicked()
{
    ui.textBrowser_01->append("Start do something ...");

    QThread::sleep(5);

    ui.textBrowser_01->append("Finishing this operation.");
}

void QThreadTest::OnBtn02Clicked()
{
    ui.textBrowser_02->append(QString("主线程id = %1").arg((int)QThread::currentThreadId()));

    // 启动子线程,开始执行 run 函数中的耗时操作,避免阻塞主线程。
    workThread->start();
}

void QThreadTest::GetResult(QString msg)
{
    ui.textBrowser_02->append("workThread: " + msg);
}

效果如下图所示:

点击 Btn01 后直接导致程序卡住,无法响应其它的操作。点击Btn02后会在子线程中执行耗时操作,此时主 UI 线程仍然可以响应用户的操作,不会阻塞主线程。


【注意】

标签:run,Qt,QThreadTest,线程,WorkThread,多线程,QThread,函数
From: https://www.cnblogs.com/Jeffxu/p/17925023.html

相关文章

  • Qt&&C++ 实现Tcp Server
    关于Qt&C++实现Tcp服务器的一些简易使用笔记... "材料"准备#include<QTcpServer>//Server需要包含该头文件,Client则不用#include<QTcpSocket>#include<QHostAddress>服务器流程简要1.实例化一个QTcpServer对象:  QTcpServer*server=newQTcpServer(this);2......
  • mqtt 共享订阅简单说明
    mqtt是一个比较常用的iot协议,5.0支持共享订阅,共享订阅是一个特别方便的功能,可以实现业务的高可用,以及提升消息的处理参考格式共享订阅格式$share/{ShareName}/{TopicFilter}ShareName是一个共享名称,可以实现业务组的能力,TopicFilter}可以对于订......
  • C++ Qt开发:Charts折线图绑定事件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QCharts折线图的常用方法及灵活运用。在上一篇文章中笔者介绍了关于QCharts绘图组件的详细使用方......
  • C++ Qt开发:ProgressBar进度条组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍ProgressBar进度条组件的常用方法及灵活运用。ProgressBar(进度条)是在Qt中常用的用户界面组件之一,用......
  • C++ Qt开发:DateTime日期时间组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QDateTime日期与时间组件的常用方法及灵活运用。在Qt中,日期和时间的处理通常使用QDateTime类。QD......
  • C++ Qt开发:Slider滑块条组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍Slider滑块条组件的常用方法及灵活运用。当涉及到C++Qt开发中的Slider滑块条组件时,你可能会用到QS......
  • C++ Qt开发:CheckBox多选框组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍CheckBox单行输入框组件的常用方法及灵活运用。QCheckBox是Qt中用于实现复选框的组件,它提供了丰......
  • C++ Qt开发:ComboBox下拉组合框组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍ComboBox下拉组合框组件的常用方法及灵活运用。在Qt中,ComboBox(组合框)是一种常用的用户界面控件,它提......
  • C++ Qt开发:RadioButton单选框分组组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QRadioButton单选框组件以及与之交互的QButtonGroup类的常用方法及灵活运用。QRadioButton是Qt框架......
  • C++ Qt开发:SpinBox数值微调框组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QSpinBox精度数值组件的常用方法及灵活运用。QSpinBox是Qt框架中的一个部件(Widget),用于提供一个方便......