最精准的定时器qt C++

The most accurate timer qt C++

我使用 QTimer 定期向服务器(MQTT 客户端)发送 'Ping' 数据包。但它的计时器并不是绝对准确的。经过一段时间的工作后,它有一些延迟和服务器断开连接。 我尝试使用不同的 Qt::TimerType,但它没有帮助。 我需要最准确的计时器。你有什么想法吗?

谢谢!


编辑(Frederik 解决方案)


我做过这样的事情:

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

运行 单独的 QThread 上的 QTimer,它不执行任何其他操作。 如果您是 运行 已经繁忙的线程上的定时器,则超时事件可能不会准时出现或根本不会出现。

创建一个工人 class 例如"PingPacketWorker",实现一个可以执行 ping 操作的插槽。 制作一个 QThread。 连接您的 QTimer 和 PingPacketWorker signal/slots。 启动定时器。 在 PingPacketWorker 和 QTimer 上调用 moveToThread,由于 moveToThread,定时器应该重新启动,注意你只能在所有者线程上启动/停止它!

您还可以提高 QThread 的优先级,因为您要求 "the most accurate" 解决方案...

更新:

此外,设置 QTimer::setTimerType(Qt::PreciseTimer)

默认值 Qt::CoarseTimer 不太精确(间隔的 5%)

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