QThread如何优雅实现暂停(挂起)功能

QThread如何优雅实现暂停(挂起)功能一、实现思路QThread中有start、quit,但是没有pause,那么我们想要实现这个功能。我们继承QThread,重写run();第一反应是不是应该添加个标志,在run()中判断暂停状态。嗯,没错,不过我们不能用普通变量,否则有线程非安全风险。这里使用C++提供的原子类型std::atomic_bool。线程暂停期间,不能空跑消耗cpu,故我们使用Qt条件变量QWaitCondition,配合QMutex。大概就是这么点内容吧,实现代码如下:Thread.h#include&lt

大家好,又见面了,我是你们的朋友全栈君。

一、实现思路

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,即可下载。

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140496.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Idea激活码最新教程2021.1.1版本,永久有效激活码,亲测可用,记得收藏

    Idea激活码最新教程2021.1.1版本,永久有效激活码,亲测可用,记得收藏Idea 激活码教程永久有效 2021 1 1 激活码教程 Windows 版永久激活 持续更新 Idea 激活码 2021 1 1 成功激活

    2025年5月22日
    0
  • linux强制删除只读文件夹,强制删除文件夹linux的方法是什么

    linux强制删除只读文件夹,强制删除文件夹linux的方法是什么灰烬里等你丶回答数:14479|被采纳数:22016-12-1714:18:36linux下删除文件的命令是rm;以下分两种介绍删除方法:对于目录文件的删除:#rf-rffilename对于非目录文件的删除:#rffilename之所以对于目录文件的删除加上了强制参数是因为在linux对目录文件的删除是递归式的;rm的参数如下所示:OPTIONSRemove(unlink)t…

    2022年6月13日
    35
  • (转载)如何画好架构图[通俗易懂]

    (转载)如何画好架构图[通俗易懂](转载)如何画好架构图标签(空格分隔):系统设计转载自阿里巴巴中间件公众号。原文地址:"如何画好架构图"写在前面当我们想用一张或几张图来描述一下我们的系统时,是不是许

    2022年8月1日
    3
  • 操作系统维护相关总结「建议收藏」

    操作系统维护相关总结「建议收藏」操作系统维护相关总结声明:引用请注明出处http://blog.csdn.net/lg1259156776/说明:由于前段时间遭受了电脑固态硬盘故障系统崩溃,数据未及时备份无法读取而导致的痛苦,这里

    2022年8月3日
    3
  • java invoke 方法说明_java中的反射,invoke方法

    java invoke 方法说明_java中的反射,invoke方法invoke,就是通过函数名反射调用相应的函数。以下代码简单地介绍了java反射中invoke方法packageorg.curry.tool;importjava.lang.reflect.Method;publicclassInvokeMethods{publicstaticvoidmain(String[]args){Employeeemp=newEmployee(…

    2022年5月1日
    41
  • Matlab中axis函数使用

    Matlab中axis函数使用目录一.语法1.输入参数2.输出参数二.说明三.示例1.设置坐标轴范围2.使用半自动坐标轴范围3.设置多个坐标轴的坐标轴范围4.显示绘图而不显示坐标区背景5.使用紧凑的坐标轴范围并返回值6.更改坐标系的方向7.添加新绘图时保留当前的坐标轴范围axis函数是设置坐标轴范围和纵横比。一.语法axis(limits)axisstyleaxismodeaxisydirectionaxisvisibility

    2022年5月31日
    93

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号