Qt线程控制【启动、暂停、继续、退出】

一、前言

在我很久之前的文章【学习QT之多线程编程两种方式详解】中,已经论述过Qt中使用线程的两中方式了。

在子线程中,我们往往希望它干一些费时的任务,所以经常会需要使用死循环。也许你会想到如下写法:

void run()
{
	while(1) {
		//子线程执行任务
	}
}

或者是

bool runFlag;

void run()
{
	while(runFlag) {
		//子线程执行任务
	}
}
  • 方法1:倾向于单片机死循环的写法,但是这种写法实测是无法关闭线程的,使用stop()exit()都无法关闭线程;
  • 方法2:使用标志变量,我们可以通过改变标志变量的状态,来控制子线程任务的执行,这个方法比方法1要好一点,但是也无法精准的控制子线程

二、官方推荐方法

  • 采用isInterruptionRequested()方法控制线程是否停止,该方法只有qt5才具备;
  • 采用锁m_mutex来决定线程是否暂停。
  • 用一个while循环使子线程一直处于运行状态。
  • 如果该线程上运行的任务应该停止,则返回true。可以通过requestinterrupt()请求中断。

线程类

#ifndef TESTTHREAD_H
#define TESTTHREAD_H

#include <QThread>
#include <QDebug>
#include <QMutex>
#include <QDateTime>

class TestThread : public QThread
{
    Q_OBJECT
public:
    TestThread();

    QMutex m_mutex;		//锁
    void pause();		//暂停
    void resume();		//继续
    void exitThread();	//结束

protected:
    void run();
};

#endif // TESTTHREAD_H

#include "testthread.h"

TestThread::TestThread()
{

}

void TestThread::run()
{
    while (!this->isInterruptionRequested()) {
        QMutexLocker lock(&m_mutex);

        // to do something
        qDebug()<<QDateTime::currentDateTime();

        msleep(200);
    }

}

void TestThread::pause()
{
    m_mutex.lock();
}

void TestThread::resume()
{
    m_mutex.unlock();
}

void TestThread::exitThread()
{
    this->requestInterruption();
}


在这里插入图片描述

主类调用线程类

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <qDebug>

#include "testthread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

public:
    TestThread* testThread{nullptr};

private slots:
    void on_pushButton_start_clicked();

    void on_pushButton_pause_clicked();

    void on_pushButton_resume_clicked();

    void on_pushButton_exit_clicked();

private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

}

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

void MainWindow::on_pushButton_start_clicked()
{
    testThread = new TestThread;
    testThread->start();
}

void MainWindow::on_pushButton_pause_clicked()
{
    if(!testThread) {
        return;
    }

    testThread->pause();
}

void MainWindow::on_pushButton_resume_clicked()
{
    if(!testThread) {
        return;
    }

    testThread->resume();
}

void MainWindow::on_pushButton_exit_clicked()
{
    if(!testThread) {
        return;
    }

    testThread->exitThread();

    testThread->wait();

    delete testThread;

    testThread = nullptr;
}

Qt中,线程暂停和等待信号再启动可以通过多种方式实现。以下是几种常见的方法: 1. **使用QThread和信号槽机制**: - 创建一个继承自QThread的类。 - 在该类中定义一个槽函数用于暂停线程。 - 使用QWaitCondition和QMutex来实现线程暂停和唤醒。 ```cpp #include <QThread> #include <QWaitCondition> #include <QMutex> class MyThread : public QThread { Q_OBJECT public: MyThread(QObject *parent = nullptr) : QThread(parent), m_paused(false) {} protected: void run() override { while (!isInterruptionRequested()) { { QMutexLocker locker(&m_mutex); if (m_paused) { m_waitCondition.wait(&m_mutex); } } // 线程的工作代码 // ... // 模拟一些工作 QThread::sleep(1); } } public slots: void pause() { QMutexLocker locker(&m_mutex); m_paused = true; } void resume() { QMutexLocker locker(&m_mutex); m_paused = false; m_waitCondition.wakeAll(); } private: QMutex m_mutex; QWaitCondition m_waitCondition; bool m_paused; }; ``` 2. **使用QEventLoop和信号槽机制**: - 在线程的工作函数中使用QEventLoop。 - 通过信号槽机制控制QEventLoop的退出,从而实现线程暂停和恢复。 ```cpp #include <QThread> #include <QEventLoop> class MyThread : public QThread { Q_OBJECT public: MyThread(QObject *parent = nullptr) : QThread(parent), m_paused(false) {} protected: void run() override { QEventLoop loop; connect(this, &MyThread::resumeSignal, &loop, &QEventLoop::quit); while (!isInterruptionRequested()) { if (m_paused) { loop.exec(); } // 线程的工作代码 // ... // 模拟一些工作 QThread::sleep(1); } } public slots: void pause() { m_paused = true; } void resume() { m_paused = false; emit resumeSignal(); } signals: void resumeSignal(); private: bool m_paused; }; ``` 3. **使用QSemaphore**: - 使用QSemaphore来控制线程暂停和恢复。 ```cpp #include <QThread> #include <QSemaphore> class MyThread : public QThread { Q_OBJECT public: MyThread(QObject *parent = nullptr) : QThread(parent), m_semaphore(0) {} protected: void run() override { while (!isInterruptionRequested()) { m_semaphore.acquire(); // 线程的工作代码 // ... // 模拟一些工作 QThread::sleep(1); } } public slots: void pause() { m_semaphore.acquire(); } void resume() { m_semaphore.release(); } private: QSemaphore m_semaphore; }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值