The most accurate timer qt C++

2020-05-11 04:14发布

I use QTimer to send periodically 'Ping' packet to the server (MQTT client). But it timer is not absolutely accurate. After some time of working it has some delay and server broken connection. I try to use different Qt::TimerType, but it does not help. I need the most accurate timer. Do you have any ideas?

Thank you!


EDIT (Frederik solution)


I have done something this:

tthread.h

class TThread : public QThread
{
    Q_OBJECT

    void run();

public:
    explicit TThread(QObject *parent = 0);

signals:

private slots:
    void timerOut();
};

tthread.cpp

TThread::TThread(QObject *parent) : QThread(parent)
{

}

void TThread::run()
{
    QTimer timer;
    connect(&timer, SIGNAL(timeout()), this, SLOT(timerOut()), Qt::DirectConnection);
    timer.start(1000);
    timer.moveToThread(this);
    exec();
}

void TThread::timerOut()
{
    QTime time = QTime();
    qDebug() << time.currentTime().toString();
}

main.cpp

TThread thread;
thread.start();
thread.setPriority(QThread::HighPriority);

2条回答
够拽才男人
2楼-- · 2020-05-11 04:23
#pragma once

#include <cstdint>
#include <QObject>

class PrecisePolling : public QObject
{
    Q_OBJECT
private:
    std::uint64_t previousPollingTime;
public:
    PrecisePolling();

public slots:
    void doPolling();

#include "precisepolling.h"
#include "QDateTime"
#include <QDebug>

PrecisePolling::PrecisePolling()
    : previousPollingTime(QDateTime::currentMSecsSinceEpoch())
{}

void PrecisePolling::doPolling()
{
    const std::uint64_t ms = QDateTime::currentMSecsSinceEpoch();
    qDebug() << ms - previousPollingTime;
    previousPollingTime = ms;
}

#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include "precisepolling.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QThread thread;
    QTimer timer;
    PrecisePolling pp;

    timer.setInterval(1000);
    timer.setTimerType(Qt::PreciseTimer);

    QObject::connect(&timer, &QTimer::timeout, &pp, &PrecisePolling::doPolling);
    timer.start();
    timer.moveToThread(&thread);
    pp.moveToThread(&thread);

    thread.start(QThread::Priority::TimeCriticalPriority);

    return a.exec();
}
查看更多
神经病院院长
3楼-- · 2020-05-11 04:30

Run a QTimer on a separate QThread which doesn't do anything else. If you're running the timer on an already busy thread the timeout events may not come on time or not at all.

Make a worker class e.g. "PingPacketWorker", implement a slot that does pinging. Make a QThread. Connect your QTimer and PingPacketWorker signal/slots. Start the timer. Call moveToThread on the PingPacketWorker and the QTimer, the timer should restart because of moveToThread, note you can only start / stop it on the owner thread!

You could also increase your QThread's priority since you asked for "the most accurate" solution ...

Update:

Also, set QTimer::setTimerType(Qt::PreciseTimer)

The default Qt::CoarseTimer is less precise (5% of the interval)

查看更多
登录 后发表回答