Qt 精确定时器_精度

Qt 精确定时器

文章目录


关键字:

​Qt​​、

​定时器​​、

​Qtimer​​、

​线程​​、

​精度​

摘要

众所周知,​​Qt ​​​的​​QTimer​​​定时的精度,那是稀里糊涂呀,所以在遇到需要高精度的定时器的时候,就没法直接只用QTimer定时器了,只能自己搞一个了。今天分享两种方式,一种是利用Win的相关API实现的,也是​​Google​​来的这里做一下分享吧。一种就是线程了,其实原理很简单,就是一个线程开while,靠睡眠时间来触发信号。

1 QTimer 定时器类型选择

其实​​QTimer​​定时器也是有进度可以选着的。官网描述如下,如果可以接受的话,其实可以通过定时器类型来确定,包括我后期使用中,其实大部分还是使用了Qt的官方定时器。

enum Qt::TimerType

The timer type indicates how accurate a timer can be.

ConstantValueDescriptionQt::PreciseTimer0Precise timers try to keep millisecond accuracyQt::CoarseTimer1Coarse timers try to keep accuracy within 5% of the desired intervalQt::VeryCoarseTimer2Very coarse timers only keep full second accuracy

On UNIX (including Linux, macOS, and iOS), Qt will keep millisecond accuracy for Qt::PreciseTimer. For Qt::CoarseTimer, the interval will be adjusted up to 5% to align the timer with other timers that are expected to fire at or around the same time. The objective is to make most timers wake up at the same time, thereby reducing CPU wakeups and power consumption.

On Windows, Qt will use Windows’s Multimedia timer facility (if available) for Qt::PreciseTimer and normal Windows timers for Qt::CoarseTimer and Qt::VeryCoarseTimer.

On all platforms, the interval for Qt::VeryCoarseTimer is rounded to the nearest full second (e.g. an interval of 23500ms will be rounded to 24000ms, and 20300ms to 20000ms).

​Qt::PreciseTimer​​ 毫米级高精度定时器

​Qt::CoarseTimer​​ 粗略计时器,进度控制在5%以内

​Qt::VeryCoarseTimer​​ 非常粗糙的定时器,这个基本是个废废吧

2 第一种精确定时器

这个就是参考​​Windows​​下多媒体定时器为改造的一个高性能定时器。弊端呢就是,这个是没法夸平台的

Pro中添加一下代码

LIBS += -lwinmm

这里就直接上代码

#ifndef TURING_WIN_PERFORMANCETIMER_H
#define TURING_WIN_PERFORMANCETIMER_H

#include <QObject>

#include "windows.h"
/**
* @brief The Turing_Win_PerformanceTimer class
* Win平台下,高精度毫秒级定时器
* 这里使用了win的api,所以在linux下无法使用
*/
class Turing_Win_PerformanceTimer : public QObject
{
Q_OBJECT
public:
explicit Turing_Win_PerformanceTimer(QObject *parent = nullptr);
~Turing_Win_PerformanceTimer();

signals:
void timeout();
public slots:
void start(int timeInterval);
void stop();
friend WINAPI void CALLBACK PeriodCycle(uint,uint,DWORD_PTR,DWORD_PTR,DWORD_PTR);
private:
int m_interval;
int m_id;

};

#endif // TURING_WIN_PERFORMANCETIMER_H
#include "turing_win_performancetimer.h"




#ifdef __MINGW32__
#define TIME_KILL_SYNCHRONOUS 0x0100
#endif

Turing_Win_PerformanceTimer::Turing_Win_PerformanceTimer(QObject *parent)
: QObject{parent}
{
m_id=0;
}

Turing_Win_PerformanceTimer::~Turing_Win_PerformanceTimer()
{
stop();
}
void CALLBACK PeriodCycle(uint timerId,uint,DWORD_PTR user,DWORD_PTR,DWORD_PTR)
{
Q_UNUSED(timerId)
Turing_Win_PerformanceTimer *t=reinterpret_cast<Turing_Win_PerformanceTimer *>(user);
emit t->timeout();
}
void Turing_Win_PerformanceTimer::start(int timeInterval)
{
m_id = timeSetEvent(timeInterval,1,PeriodCycle,(DWORD_PTR)this,TIME_CALLBACK_FUNCTION|TIME_PERIODIC|TIME_KILL_SYNCHRONOUS);
}
void Turing_Win_PerformanceTimer::stop()
{
if(m_id)
{
timeKillEvent(m_id);
m_id=0;
}
}

3 第二种线程定时器

这里也直接上代码,这种感觉有点浪费资源。

class SpeedThread :  public QThread
{
Q_OBJECT
public:
/**
* @brief run
* 重载线程函数
*/
virtual void run();
signals:
void signalselfInspection(int number);
void signalSelfInspectionfinished();
public:
bool runFlag = true;
private:
int m_number = 0;
bool flagDESC = false;

};
void SpeedThread::run()
{
while (runFlag)
{
emit signalselfInspection(m_number);
if(flagDESC)
{
if(m_number == 0)
{
runFlag = !runFlag;
flagDESC = !flagDESC;
emit signalSelfInspectionfinished();
}
m_number--;
}
else
{
m_number++;
if(m_number == 100)
{
flagDESC = !flagDESC;
}
}
msleep(8);
}
}

Qt 精确定时器_线程_02