最精准的定时器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();
}
我使用 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();
}