Qt 多线程的两种实现方式

Qt 多线程的两种实现方式

1. 从QThread类继承再重写 run 函数

实现流程:

  1. 继承自QThread类
  2. 重写run函数,其中run函数里面的代码为线程的执行代码
  3. 调用start函数启动线程

程序示例:

  • WorkThread.h 文件
cpp 复制代码
#ifndef WORKTHREAD_H
#define WORKTHREAD_H

#include <QThread>

class WorkThread : public QThread
{
    Q_OBJECT
public:
    explicit WorkThread(QObject *parent = nullptr);
    ~WorkThread();

public:
    void StartThread();
    void StopThread();
    void TerminateThread();

protected:
    void run() override;				// 重写run函数

private:
    void DealValue(int& nValue);

signals:
    void SignalSendValue(QString, int);

private:
    bool m_bRunFlag;

};

#endif // WORKTHREAD_H
  • WorkThread.cpp 文件
cpp 复制代码
#include "WorkThread.h"
#include <QDebug>

WorkThread::WorkThread(QObject *parent) : QThread(parent), m_bRunFlag(false)
{

}

WorkThread::~WorkThread()
{
    qDebug() << "Release WorkThread!";
}

void WorkThread::StartThread()
{
    m_bRunFlag = true;
    start();
}

void WorkThread::StopThread()
{
    m_bRunFlag = false;
    quit();
    wait();
}

void WorkThread::TerminateThread()
{
    terminate();
    wait();
}

void WorkThread::run()
{
    int nValue = 0;

    while (m_bRunFlag)
    {
        DealValue(nValue);
        Qt::HANDLE hHandle = QThread::currentThreadId();
        emit SignalSendValue(QString::number(reinterpret_cast<quintptr>(hHandle), 16), nValue);
        QThread::msleep(100);
    }
}

void WorkThread::DealValue(int &nValue)
{
    nValue++;

    if (nValue > 100)
        nValue = 1;
}
  • MainWindow.h文件
cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "WorkThread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    void SlotRecieveValue(QString strThreadID, int nValue);

private slots:
    void on_btnStart_clicked();
    void on_btnStop_clicked();
    void on_btnTerminate_clicked();

private:
    Ui::MainWindow *ui;
    WorkThread* m_pWorkThread;
};
#endif // MAINWINDOW_H
  • MainWindow.cpp文件
cpp 复制代码
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->labelMainThreadID->setText(QString("Thread ID = 0x%1").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16)));

    m_pWorkThread = new WorkThread(this);
    connect(m_pWorkThread, &WorkThread::SignalSendValue, this, &MainWindow::SlotRecieveValue);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::SlotRecieveValue(QString strThreadID, int nValue)
{
    ui->labelValue->setText(QString("Thread ID = 0x%1, Value = %2").arg(strThreadID).arg(nValue));
}


void MainWindow::on_btnStart_clicked()
{
    m_pWorkThread->StartThread();
}

void MainWindow::on_btnStop_clicked()
{
    m_pWorkThread->StopThread();
}

void MainWindow::on_btnTerminate_clicked()
{
    m_pWorkThread->TerminateThread();
}

2. 使用QObject::moveToThread()函数

实现流程:

  1. 创建一个工作类继承自QObject;
  2. 创建一个工作类线程对象和一个QThread对象,调用QObject::moveToThread()将工作对象移至线程中;
  3. 调用QThread对象的start函数,通过发送信号,后续工作对像的槽函数都会在独立的线程中执行;

文字解释流程相对比较抽象,下面看一个基于上面例子改造的示例;

  • ThreadWorker.h 文件 (线程工作者对象)
cpp 复制代码
#ifndef THREADWORKER_H
#define THREADWORKER_H

#include <QObject>

class ThreadWorker : public QObject
{
    Q_OBJECT

public:
    explicit ThreadWorker(QObject *parent = nullptr);
    ~ThreadWorker();

public:
    void SetRunFlag(bool bRunFlag);

public slots:
    void SlotDoWork();          // 槽函数,通过外部的信号关联,其执行会在独立的线程中

private:
    void DealValue(int& nValue);

signals:
    void SignalDoWork();
    void SignalSendValue(QString, int);

private:
    bool m_bRunFlag;
};

#endif // THREADWORKER_H
  • ThreadWorker.cpp 文件
cpp 复制代码
#include "ThreadWorker.h"
#include <QDebug>
#include <QThread>

ThreadWorker::ThreadWorker(QObject *parent) : QObject(parent), m_bRunFlag(false)
{

}

ThreadWorker::~ThreadWorker()
{
    qDebug() << "Release ThreadWorker!";
}

void ThreadWorker::SetRunFlag(bool bRunFlag)
{
    m_bRunFlag = bRunFlag;
}

void ThreadWorker::SlotDoWork()
{
    int nValue = 0;

    while (m_bRunFlag)
    {
        DealValue(nValue);
        Qt::HANDLE hHandle = QThread::currentThreadId();
        emit SignalSendValue(QString::number(reinterpret_cast<quintptr>(hHandle), 16), nValue);
        QThread::msleep(100);
    }
}

void ThreadWorker::DealValue(int &nValue)
{
    nValue++;

    if (nValue > 100)
        nValue = 1;
}
  • MainWindow.h 文件
cpp 复制代码
#ifndef WORKTHREAD_H
#define WORKTHREAD_H

#include <QThread>

class WorkThread : public QThread
{
    Q_OBJECT
public:
    explicit WorkThread(QObject *parent = nullptr);
    ~WorkThread();

public:
    void StartThread();
    void StopThread();
    void TerminateThread();

protected:
    void run() override;

private:
    void DealValue(int& nValue);

signals:
    void SignalSendValue(QString, int);

private:
    bool m_bRunFlag;

};

#endif // WORKTHREAD_H
  • MainWindow.cpp 文件
cpp 复制代码
#include "WorkThread.h"
#include <QDebug>

WorkThread::WorkThread(QObject *parent) : QThread(parent), m_bRunFlag(false)
{

}

WorkThread::~WorkThread()
{
    qDebug() << "Release WorkThread!";
}

void WorkThread::StartThread()
{
    m_bRunFlag = true;
    start();
}

void WorkThread::StopThread()
{
    m_bRunFlag = false;
    quit();
    wait();
}

void WorkThread::TerminateThread()
{
    terminate();
    wait();
}

void WorkThread::run()
{
    int nValue = 0;

    while (m_bRunFlag)
    {
        DealValue(nValue);
        Qt::HANDLE hHandle = QThread::currentThreadId();
        emit SignalSendValue(QString::number(reinterpret_cast<quintptr>(hHandle), 16), nValue);
        QThread::msleep(100);
    }
}

void WorkThread::DealValue(int &nValue)
{
    nValue++;

    if (nValue > 100)
        nValue = 1;
}
相关推荐
用户805533698035 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner5 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz10 天前
QML Hello World 入门示例
qt
xcyxiner13 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner13 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner14 天前
DicomViewer (添加模型类)3
qt
xcyxiner14 天前
DicomViewer (目录调整) 2
qt
xcyxiner14 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00616 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术16 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript