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;
}
相关推荐
努力努力再努力wz1 分钟前
【C++深入系列】:模版详解(上)
java·c语言·开发语言·c++
旋风小飞棍31 分钟前
spark和hadoop的区别与联系
大数据·开发语言·scala
我慢慢地也过来了1 小时前
servlet+jdbc+jsp实现增加操作
java·开发语言·servlet
AI量化投资实验室1 小时前
年化112.5%,最大回撤24.3%,卡玛比率4.62 | polars因子引擎重构完成(python源代码下载)
开发语言·python·重构
笑川 孙1 小时前
为什么Makefile中的clean需要.PHONY
开发语言·c++·面试·makefile·make·技术
Heisenberg~2 小时前
C++回溯算法详解
开发语言·c++·算法
朴拙数科2 小时前
Stable Diffusion秋叶整合包V4独立版Python本地API连接指南
开发语言·python·stable diffusion
z_mazin2 小时前
JavaScript 渲染内容爬取:Puppeteer 入门
开发语言·javascript·ecmascript
虽千万人 吾往矣2 小时前
golang channel源码
开发语言·后端·golang