多线程

继承QThread

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include <QDebug>
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class WorkerThread;

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

    /* 在 MainWindow 类里声明对象 */
    WorkerThread *workerThread;

    /* 声明一个按钮,使用此按钮点击后开启线程 */
    QPushButton *pushButton;

private slots:
    /* 槽函数,用于接收线程发送的信号 */
    void handleResults(const QString &result);

    /* 点击按钮开启线程 */
    void pushButtonClicked();
};

/* 新建一个 WorkerThread 类继承于 QThread */
class WorkerThread : public QThread
{
    /* 用到信号槽即需要此宏定义 */
    Q_OBJECT

public:
    WorkerThread(QWidget *parent = nullptr) {
        Q_UNUSED(parent);
    }

    /* 重写 run 方法,继承 QThread 的类,只有 run 方法是在新的线程里 */
    void run() override {
        QString result = "线程开启成功";
        /* 这里写上比较耗时的操作 */
        // ...
        // 延时 2s,把延时 2s 当作耗时操作
        sleep(2);

        /* 发送结果准备好的信号 */
        emit resultReady(result);
    }

signals:
    /* 声明一个信号,译结果准确好的信号 */
    void resultReady(const QString &s);
};



#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);

    /* 设置位置与大小 */
    this->setGeometry(0, 0, 800, 480);
    /* 对象实例化 */
    pushButton = new QPushButton(this);
    workerThread = new WorkerThread(this);
    /* 按钮设置大小与文本 */
    pushButton->resize(100, 40);
    pushButton->setText("开启线程");

    /* 信号槽连接 */
    connect(workerThread, SIGNAL(resultReady(QString)),
            this, SLOT(handleResults(QString)));
    connect(pushButton, SIGNAL(clicked()),
            this, SLOT(pushButtonClicked()));
}

MainWindow::~MainWindow()
{
    /* 进程退出,注意本例 run()方法没写循环,此方法需要有循环才生效 */
   workerThread->quit();

   /* 阻塞等待 2000ms 检查一次进程是否已经退出 */
   if (workerThread->wait(2000)) {
       qDebug()<<"线程已经结束!"<<endl;
   }
    delete ui;
}

void MainWindow::handleResults(const QString &result)
{
    /* 打印出线程发送过来的结果 */
    qDebug()<<result<<endl;
}

void MainWindow::pushButtonClicked()
{
    /* 检查线程是否在运行,如果没有则开始运行 */
    if (!workerThread->isRunning())
        workerThread->start();
}

继承QThread

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include <QDebug>
#include <QPushButton>
#include <QMutexLocker>
#include <QMutex>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class Worker;

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

    /* 开始线程按钮 */
    QPushButton *pushButton1;
    /* 打断线程按钮 */
    QPushButton *pushButton2;
    /* 全局线程 */
    QThread workerThread;
    /* 工人类 */
    Worker *worker;

private slots:
    /* 按钮 1 点击开启线程 */
    void pushButton1Clicked();
    /* 按钮 2 点击打断线程 */
    void pushButton2Clicked();
    /* 用于接收工人是否在工作的信号 */
    void handleResults(const QString &);
signals:
    /* 工人开始工作(做些耗时的操作 ) */
    void startWork(const QString &);
};

/* Worker 类,这个类声明了 doWork1 函数,
 * 将整个 Worker 类移至线程 workerThread
 * */
class Worker : public QObject
{
    Q_OBJECT

private:
    /* 互斥锁 */
    QMutex lock;
    /* 标志位 */
    bool isCanRun;
public slots:
    /* 耗时的工作都放在槽函数下,工人可以有多份不同的工作,但是每次只能去做一份 */
    void doWork1(const QString &parameter) {
        /* 标志位为真 */
        isCanRun = true;

        /* 死循环 */
        while (1) {
            /* 此{}作用是 QMutexLocker 与 lock 的作用范围,获取锁后,
            * 运行完成后即解锁 */
            {
                QMutexLocker locker(&lock);
                /* 如果标志位不为真 */
                if (!isCanRun) {
                    /* 跳出循环 */
                    break;
                }
            }
            /* 使用 QThread 里的延时函数,当作一个普通延时 */
            QThread::sleep(2);

            emit resultReady(parameter + "doWork1 函数");
        }
        /* doWork1 运行完成,发送信号 */
        emit resultReady("打断 doWork1 函数");
    }
    // void doWork2();...
public:
    /* 打断线程(注意此方法不能放在槽函数下) */
    void stopWork() {
        qDebug()<<"打断线程"<<endl;
        /* 获取锁后,运行完成后即解锁 */
        QMutexLocker locker(&lock);
        isCanRun = false;
    }

signals:
    /* 工人工作函数状态的信号 */
    void resultReady(const QString &result);
};

#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);

    /* 设置显示位置与大小 */
    this->setGeometry(0, 0, 800, 480);
    pushButton1 = new QPushButton(this);
    pushButton2 = new QPushButton(this);

    /* 设置按钮的位置大小 */
    pushButton1->setGeometry(300, 200, 80, 40);
    pushButton2->setGeometry(400, 200, 80, 40);

    /* 设置两个按钮的文本 */
    pushButton1->setText("开启线程");
    pushButton2->setText("打断线程");

    /* 工人类实例化 */
    worker = new Worker;

    /* 将 worker 类移至线程 workerThread */
    worker->moveToThread(&workerThread);

    /* 信号槽连接 */
    /* 线程完成销毁对象 */
    connect(&workerThread, SIGNAL(finished()),
    worker, SLOT(deleteLater()));
    connect(&workerThread, SIGNAL(finished()),
    &workerThread, SLOT(deleteLater()));

    /* 发送开始工作的信号,开始工作 */
    connect(this, SIGNAL(startWork(QString)),
    worker, SLOT(doWork1(QString)));

    /* 接收到 worker 发送过来的信号 */
    connect(worker, SIGNAL(resultReady(QString)),
    this, SLOT(handleResults(QString)));

    /* 点击按钮开始线程 */
    connect(pushButton1, SIGNAL(clicked()),
    this, SLOT(pushButton1Clicked()));

    /* 点击按钮打断线程 */
    connect(pushButton2, SIGNAL(clicked()),
    this, SLOT(pushButton2Clicked()));
}

MainWindow::~MainWindow()
{
    /* 打断线程再退出 */
    worker->stopWork();
    workerThread.quit();

    /* 阻塞线程 2000ms,判断线程是否结束 */
    if (workerThread.wait(2000)) {
        qDebug()<<"线程结束"<<endl;
    }
    delete ui;
}

void MainWindow::pushButton1Clicked()
{
    /* 字符串常量 */
    const QString str = "正在运行";
    /* 判断线程是否在运行 */
    if(!workerThread.isRunning()) {
        /* 开启线程 */
        workerThread.start();
    }
    /* 发送正在运行的信号,线程收到信号后执行后返回线程耗时函数 + 此字符串 */
    emit this->startWork(str);
}

void MainWindow::pushButton2Clicked()
{
    /* 如果线程在运行 */
    if(workerThread.isRunning()) {
        /* 停止耗时工作,跳出耗时工作的循环 */
        worker->stopWork();
    }
}

void MainWindow::handleResults(const QString & results)
{
    /* 打印线程的状态 */
    qDebug()<<"线程的状态:"<<results<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值