相关文章推荐
任性的菠菜  ·  jQuery UI 实例 – ...·  1 年前    · 
怕老婆的生姜  ·  React ...·  1 年前    · 
率性的水煮鱼  ·  原理+代码详解 | ...·  1 年前    · 

一、实现思路

QThread中有start、quit,但是没有pause,那么我们想要实现这个功能。

  • 我们继承QThread,重写run();
  • 第一反应是不是应该添加个标志,在run()中判断暂停状态。嗯,没错,不过我们不能用普通变量,否则有线程非安全风险。这里使用C++提供的原子类型std::atomic_bool。
  • 线程暂停期间,不能空跑消耗cpu,故我们使用Qt条件变量QWaitCondition,配合QMutex。

大概就是这么点内容吧,实现代码如下:

Thread.h

#include <QThread>
#include <atomic>
#include <QMutex>
#include <QWaitCondition>
class Thread : public QThread
    Q_OBJECT
public:
    Thread(QObject *parent = nullptr);
    ~Thread() override;
    enum State
        Stoped,     ///<停止状态,包括从未启动过和启动后被停止
        Running,    ///<运行状态
        Paused      ///<暂停状态
    State state() const;
public slots:
    void start(Priority pri = InheritPriority);
    void stop();
    void pause();
    void resume();
protected:
    virtual void run() override final;
    virtual void process() = 0;
private:
    std::atomic_bool pauseFlag;
    std::atomic_bool stopFlag;
    QMutex mutex;
    QWaitCondition condition;

Thread.cpp

#include "Thread.h"
#include <QDebug>
Thread::Thread(QObject *parent)
    : QThread(parent),
      pauseFlag(false),
      stopFlag(false)
Thread::~Thread()
    stop();
Thread::State Thread::state() const
    State s = Stoped;
    if (!QThread::isRunning())
        s = Stoped;
    else if (QThread::isRunning() && pauseFlag)
        s = Paused;
    else if (QThread::isRunning() && (!pauseFlag))
        s = Running;
    return s;
void Thread::start(Priority pri)
    QThread::start(pri);
void Thread::stop()
    if (QThread::isRunning())
        stopFlag = true;
        condition.wakeAll();
        QThread::quit();
        QThread::wait();
void Thread::pause()
    if (QThread::isRunning())
        pauseFlag = true;
void Thread::resume()
    if (QThread::isRunning())
        pauseFlag = false;
        condition.wakeAll();
void Thread::run()
    qDebug() << "enter thread : " << QThread::currentThreadId();
    while (!stopFlag)
        process();
        if (pauseFlag)
            mutex.lock();
            condition.wait(&mutex);
            mutex.unlock();
    pauseFlag = false;
    stopFlag = false;
    qDebug() << "exit thread : " << QThread::currentThreadId();
  • 支持获取线程状态;
  • start()、stop()、pause()、resume()支持信号槽方式调用;
  • start()、stop()、pause()、resume()支持多次无效调用,对线程运行状态无影响。
  • 禁止子类重写run()方法,而代替为重写process()。

测试,运行效果:
在这里插入图片描述

可以看到暂停时,PauseQThread.exe的CPU使用率为0%

若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:37PauseQThread,即可下载。

一、实现思路QThread中有start、quit,但是没有pause,那么我们想要实现这个功能。我们继承QThread,重写run();第一反应是不是应该添加个标志,在run()中判断暂停状态。嗯,没错,不过我们不能用普通变量,否则有线程非安全风险。这里使用C++提供的原子类型std::atomic_bool。线程暂停期间,不能空跑消耗cpu,故我们使用Qt条件变量QWaitCondition,配合QMutex。大概就是这么点内容吧,实现代码如下:Thread.h#include &lt class startThread(QThread): #继承QThread trigger = pyqtSignal() #创建信号 def __init__(self): super(startThread, self).__init__() self.flag = 1 #自定义变量 ... 当我们使用Thread.stop()方法去停止线程时,这个方法会报错,抛出了UnsupportedOperationException异常,它在JDK中已经被声明“过期/作废”的方法,显然它在功能上有缺陷,不建议使用。 stop()方法的源码... 软件开发中,使用到线程就不可避免的要实现线程的暂停恢复停止等操作,总不可能说线程一旦启动就直接运行到结束了,中途不能停止啥的。线程的开始以及结束都比较简单,都有对应的接口可以调用,线程的暂停以及恢复就需要自己手动写个接口,关键在于使用线程锁来实现这个过程。 二.实现过程 1.1先继承QThread实现自己的线程类,声明线程锁变量,以及暂停恢复停止的接口 1.2核心代码(.h) * 线程开始 暂停 恢复 停止 例程 * V1.0 2021-12-27 #ifndef THREAD3 self.my_thread = MyThread() # 连接自定义信号和槽 self.my_thread.update_signal.connect(self.updateUI) # 启动线程 self.my_thread.start() def updateUI(self, msg): # 在UI中显示线程执行的进度 self.statusBar().showMessage(msg) 这样,就可以在UI界面中显示线程执行的进度了。需要注意的是,在UI界面中操作QObject的属性和方法必须在主线程中执行,因此需要通过自定义信号在主线程中更新UI。 希望这个回答能够帮到您。
小小知识搬运工: QThread说“It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). ” 所以说这个Object会运行在新的线程上吗? https://doc.qt.io/qt-6/qthread.html#details:~:text=It%20is%20important%20to%20remember%20that%20a%20QThread%20instance%20lives%20in%20the%20old%20thread%20that%20instantiated%20it%2C%20not%20in%20the%20new%20thread%20that%20calls%20run(). 环境篇-Windows下安装OpenSSL wy-my: 没加环境变量,按他的文章添加之后就好了