Qt实现高精度定时器

一般而言,Qt有两种使用定时器的方式, QObject和QTimer,对于第一种需要重写timerEvent事件来实现,第二种需要声明一个QTimer的对象或指针,用QTimer::timeout()信号连接槽函数,设置定时器类型mTimer.setTimerType(Qt::PreciseTimer);

第一种即使高精度的定时器,保持毫秒级别;第二种粗计时器尽量将精度保持在所需间隔的5%以内;第三种非常粗糙的计时器只能保持完整的秒精度.

#ifndef BACKENDPROIXY_H #define BACKENDPROIXY_H #include <QObject> #include <QTimer> #include <QTime> class BackendProxy : public QObject {     Q_OBJECT public:     explicit BackendProxy(QObject *parent = nullptr); signals: private slots:     void onTimeOut(); private:     QTimer mTimer;     QTime lastTime; }; #endif // BACKENDPROIXY_H #include "backendproixy.h" #include <QDebug> BackendProxy::BackendProxy(QObject *parent) : QObject(parent) {     connect(&mTimer,&QTimer::timeout,this,&BackendProxy::onTimeOut);     mTimer.setTimerType(Qt::PreciseTimer);     mTimer.start(50); } void BackendProxy::onTimeOut() {     QTime currentTime;     int elapsed = 0;     if(lastTime == QTime()){         lastTime = QTime::currentTime();     }else{         currentTime = QTime::currentTime();         elapsed = lastTime.msecsTo(currentTime);         lastTime = QTime::currentTime();     }     qDebug()<<"Run.elapsed ="<<elapsed<<"ms"; }

下面分别展示三种类型的时间间隔:

Qt::PreciseTimer:

Qt::CoarseTimer:

Qt::VeryCoarseTimer:

显而易见,第一种的精度最高,但偶尔也会超过20ms,对于一些实时性较高的通讯来说,还是达不到要求.使用线程加延时能达到最多正负1ms的误差,一下输出我使用的是10ms一个周期:

现在也贴上代码:

#ifndef PERFORMANCEFREQUENCY_H #define PERFORMANCEFREQUENCY_H #include<QThread> #include<QDebug> #include<QUdpSocket> #include <QHostAddress> #define SEND_TIME 10 class PerformanceFrequency : public QThread {     Q_OBJECT public:     explicit PerformanceFrequency(QObject *parent = nullptr);     void setThreadRunning(bool start){bRunning = start;}     void appendByte(QByteArray array);     void removeOneByte(QByteArray array); signals:     void sendJaguarJointControl(QByteArray ba);     void heartTime(int time); protected:     void run() override; private:     QList<QByteArray> listByte;     bool bRunning = true; }; #endif // PERFORMANCEFREQUENCY_H #include "performancefrequency.h" #include <QTime> #include <QMutex> #include <QMutexLocker> PerformanceFrequency::PerformanceFrequency(QObject *parent)     : QThread(parent) {     QByteArray heart;     heart[0] = 0xf0;     heart[1] = heart[2] = heart[3] = heart[4] = heart[5] = heart[6] = heart[7] =  0;     listByte.append(heart); } void PerformanceFrequency::run() {     while(bRunning){         QTime startTime = QTime::currentTime();         msleep(SEND_TIME);         for(int i = 0;i < listByte.size();i++){             emit sendJaguarJointControl(listByte.at(i));         }         QTime stopTime = QTime::currentTime();         int elapsed = startTime.msecsTo(stopTime);         emit heartTime(elapsed);         qDebug()<<"Run.elapsed ="<<elapsed<<"ms";     } } void PerformanceFrequency::appendByte(QByteArray array) {     static QMutex mutex;     QMutexLocker locker(&mutex);     listByte.append(array); } void PerformanceFrequency::removeOneByte(QByteArray array) {     static QMutex mutex;     QMutexLocker locker(&mutex);     listByte.removeOne(array); }

推荐阅读