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

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

文章目录

  • 前言
  • 一、moveToThread
    • 1.主线程头文件,主线程窗口类里面新建以下变量
    • 2.主线程生成定时器并迁移到线程中
  • 二、继承QThread,在thread里造个计时器,然后信号通信
    • 1.继承线程的写法
    • 2.主线程调用
  • 总结


前言

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

一、moveToThread

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

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

	const int m_timer_interval__ = 5000;
	QTimer* monitor_timer__ = nullptr;
	QThread* monitor_thread__ = nullptr;

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()));

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
};

代码如下,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();
}

2.主线程调用

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

总结

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

你可能感兴趣的:(QT6,QT技巧,学习总结,qt,交互,开发语言)