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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 什么是前端开发工程师?

    什么是前端开发工程师?前端工程师是web前端开发工程师的简称,它是随着web(WorldWideWeb)发展,细分出来的行业,可以说,它是时代的产物。Web前端开发技术(因为技术的更新,又称为H5开发工程师)主要包括

    2022年8月4日
    7
  • startService与bindService的区别「建议收藏」

    startService与bindService的区别「建议收藏」Android执行Service有两种方法,一种是startService,一种是bindService。下面让我们一起来聊一聊这两种执行Service方法的区别。1、生命周期上的区别执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Servi

    2022年6月1日
    36
  • JS中取余与取整

    取余6%2取整抛弃整数parseInt(7/3)向上取整(天花板嘛,代表上)Math.ceil(7/3)向下取整(地板嘛,代表下)Math.floor(7/3)四舍五入Math.round(7/3)

    2022年4月9日
    80
  • Centos7更换阿里云yum源

    Centos7更换阿里云yum源

    2021年5月31日
    117
  • listview嵌套GridView_react grid layout

    listview嵌套GridView_react grid layoutGridView嵌套GridView,对子GridView及父GridView级联删除的问题http://blog.csdn.net/amandag/archive/2007/05/31/1633395.aspx利用GridView显示主细表并添加删除、打开、关闭功能(续)http://dotnet.aspx.cc/article/f73eeaa9-2bdc-47fd-a…

    2022年10月7日
    2
  • ArcGIS二次开发基础教程(00):基础界面设计

    ArcGIS二次开发基础教程(00):基础界面设计ArcGIS二次开发基础教程(00):基础界面设计(开发环境:VS2010+ArcEngine10.2+C#;鉴于学习ArcGIS二次开发的同学都有一定的WinForm开发和ArcGIS软件使用基础,故此教程不再对一些基础内容作详细阐述)首先新建一个Windows窗体应用程序,设置Size为(700,450),再添加一个MenuStrip,输入文件,如图:添加一个ToolB…

    2022年7月23日
    13

发表回复

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

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