• QT+QTimer+QThread实现线程内的定时任务并且和主线程进行交互


    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


    前言

    在制作qt软件时,我们经常会用到qtimer定时器以及将其在非主线程中进行使用,甚至有的时候还需要和主线程进行交互。我总结了两种用法,仅供参考

    一、moveToThread

    1.主线程头文件,主线程窗口类里面新建以下变量

    代码如下:一个时间间隔,两个变量。记得初始化指针为空

    	const int m_timer_interval__ = 5000;
    	QTimer* monitor_timer__ = nullptr;
    	QThread* monitor_thread__ = nullptr;
    
    • 1
    • 2
    • 3

    2.主线程生成定时器并迁移到线程中

    代码如下:qtimer不要有parent,线程可以有。先开线程,再开定时器,开启定时器以后,再迁移到线程中即可。

    	monitor_thread__ = new QThread(this);
    	monitor_thread__->start();
    	monitor_timer__ = new QTimer();
    	connect(monitor_timer__, SIGNAL(timeout()), this, SLOT(GetResource()), Qt::DirectConnection);
    	monitor_timer__->start(m_timer_interval__);
    	monitor_timer__->moveToThread(monitor_thread__);
    
    	connect(monitor_thread__, SIGNAL(started()), monitor_timer__, SLOT(start()));
    	connect(monitor_thread__, SIGNAL(finished()), monitor_timer__, SLOT(stop()));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    GetRsource()可以换成任何你想定时执行的任务(主线程的函数即可),如果要交互,可以用信号和槽理论上时可以和主线程之间通信的。


    二、继承QThread,在thread里造个计时器,然后信号通信

    1.继承线程的写法

    代码如下,h:

    #pragma once
    #include 
    #include 
    #include 
    #include 
    class timerThread :
    	public QThread
    {
    	Q_OBJECT
    public:
    	timerThread(QObject* parent = nullptr);
    	~timerThread() override;
    
    	enum State
    	{
    		Stoped,     ///<停止状态,包括从未启动过和启动后被停止
    		Running,    ///<运行状态
    		Paused      ///<暂停状态
    	};
    	State state() const;
    private:
    	std::atomic_bool pauseFlag;
    	std::atomic_bool stopFlag;
    	QMutex mutex;
    	QWaitCondition condition;
    
    	QTimer* _timer = nullptr;
    public slots:
    	void timerRun();//用于反复跑的内容
    	void start(Priority pri = InheritPriority);
    	void stop_th();
    	void pause();
    	void resume();
    protected:
    	virtual void run() override final;
    
    signals:
    	void sendCtrlSignal();//和主线程交互触发的signal
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    代码如下,cpp:

    #include "timerThread.h"
    #include 
    timerThread::timerThread(QObject* parent)
    	: QThread(parent),
    	pauseFlag(false),
    	stopFlag(false)
    {
    }
    
    timerThread::~timerThread()
    {
    	stop_th();
    }
    
    timerThread::State timerThread::state() const
    {
    	State s = Stoped;
    	if (!timerThread::isRunning())
    	{
    		s = Stoped;
    	}
    	else if (timerThread::isRunning() && pauseFlag)
    	{
    		s = Paused;
    	}
    	else if (timerThread::isRunning() && (!pauseFlag))
    	{
    		s = Running;
    	}
    	return s;
    }
    
    void timerThread::start(Priority pri)
    {
    	QThread::start(pri);
    }
    
    void timerThread::stop_th()
    {
    	if (timerThread::isRunning())
    	{
    		stopFlag = true;
    		condition.wakeAll();
    		timerThread::quit();
    		timerThread::wait();
    	}
    }
    
    void timerThread::pause()
    {
    	if (timerThread::isRunning())
    	{
    		pauseFlag = true;
    	}
    }
    
    void timerThread::resume()
    {
    	if (timerThread::isRunning())
    	{
    		pauseFlag = false;
    		condition.wakeAll();
    	}
    }
    
    void timerThread::run()
    {
    	qDebug() << QString("开始执行计时线程") << timerThread::currentThreadId();
    	_timer = new QTimer();
    	_timer->setInterval(MODBUS_WAIT * 20);
    	connect(_timer, &QTimer::timeout, [=] {
    		if (!pauseFlag)
    		{
    			timerRun();
    		}
    		if (stopFlag)
    		{
    			_timer->stop();
    		}
    		});
    	_timer->start();
    	this->exec();
    
    	pauseFlag = false;
    	stopFlag = false;
    	qDebug() << QString("结束执行计时线程") << timerThread::currentThreadId();
    }
    
    void timerThread::timerRun()
    {
    	emit sendCtrlSignal();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    2.主线程调用

    1.挂上头文件#include “timerThread.h”
    2.主线程对应的头文件里,最上边,类外加上class timerThread;提前声明一下
    3.cpp文件里,生成一个,然后控制一下就行了,剩下的就不用我教了。最后记得主线程结束的时候,最好手动判定一下是否运行,然后释放一下。

    总结

    以上即为QTimer和QThread联合使用的学习记录。

  • 相关阅读:
    【iOS】—— KVC与KVO
    Mac M1 安装 brew
    Python基础教程:print输出带颜色的方法详解
    芯片设计:一颗芯片到底是如何诞生的(上)
    C++_特殊类的设计和单例模式
    前端学习开发之【Vue】-中
    8月5日学习笔记 glibc安装与安全用户角色权限
    K3s+Rainbond默认集群添加server节点
    深入了解 Bat 脚本:简单而强大的自动化工具——进阶版
    操控xls文件的jxl包下载
  • 原文地址:https://blog.csdn.net/u011826081/article/details/127823471