当前位置: 首页 > news >正文

Qt 多线程的两种实现方式

Qt 多线程的两种实现方式

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

实现流程:

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

程序示例:

  • WorkThread.h 文件
#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 文件
#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文件
#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文件
#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 文件 (线程工作者对象)
#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 文件
#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 文件
#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 文件
#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;
}

在这里插入图片描述

相关文章:

  • 表单对象与当前行对象的 区别
  • 基于Spring的forum系统测试报告
  • MYSQL中对行与列的操作
  • 【leetcode刷题日记】lc.238-除自身以外数组的乘积
  • redis 缓存命中率降低,该如何解决?
  • OMNIWeb 数据介绍
  • uniapp用法--uni.navigateTo 使用与参数携带的方式示例(包含复杂类型参数)
  • 合合信息大模型加速器2.0实测:当AI开始“读心术“与“考古“
  • 若依框架二次开发——若依(RuoYi)实现手机号/邮箱/用户名多方式登录
  • 【MySQL基础-18】MySQL字符函数详解:高效处理文本数据的利器
  • 说说Redis的内存淘汰策略?
  • 课程6. 决策树
  • #不同版本下,单元测试的注解使用
  • Mysql从入门到精通day5————子查询精讲
  • 人工智能的未来:从弱 AI 到通用人工智能(AGI)
  • 常用的卷积神经网络及Pytorch示例实现
  • AI+制造的破局之战(上):从技术爆发到价值穿透,谁将率先定义“智能体时代”?
  • 网络架构搭建中的 QinQ 与端口安全策略
  • python采集淘宝拍立淘按图搜索API接口,json数据示例参考
  • Java中用Stream流取出分组后每组中最大值对应的对象
  • 投票网站定制/泰州百度关键词优化
  • 模板网站建设教程视频/新媒体运营培训课程
  • 网站开发的进度怎么写/软文类型
  • 做网站时java都做什么/百度优化关键词
  • 珠海市网络营销协会的官方网站/湖南正规seo优化报价
  • 星巴克网站开发票吗/长沙官网优化公司