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

9 篇文章 2 订阅
9 篇文章 0 订阅
本文介绍了在Qt应用中,如何通过moveToThread将QTimer迁移到子线程以及如何通过继承QThread并在线程内创建计时器进行信号通信。两种方法都包含了关键步骤和示例代码,帮助理解在多线程环境下定时任务的处理。
摘要由CSDN通过智能技术生成

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


前言

在制作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 <qthread.h>
#include <atomic>
#include <QMutex>
#include <QWaitCondition>
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 <QDebug>
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联合使用的学习记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷失的walker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值