• 17452阅读
  • 20回复

[提问]QTimer定时精度的问题 [复制链接]

上一主题 下一主题
离线yearl
 

只看楼主 倒序阅读 楼主  发表于: 2014-10-16
文档中说这个定时器只会慢,不会快。
可是我遇到的问题是快啊,还快很多。
程序运行中发现的,而且不是在所有电脑上都有这个问题。可是有问题的这台电脑本身显示的时钟是正常的。这应该能说明主板频率没有问题吧?XP系统。
为了验证这个问题,我编了一个最小程序:
QTimer设了一个1000ms定时器。
系统时间显示。
定时器触发时,原时间加1s并显示,同时显示此时的系统时间。

过一段时间后,比较发现我的时钟比系统时钟快了好多。
什么问题呢?


XP、QT4.8.4
  1. #include "dialog.h"
  2. #include "ui_dialog.h"
  3. #include <QTimer>
  4. Dialog::Dialog(QWidget *parent) :
  5.     QDialog(parent),
  6.     ui(new Ui::Dialog)
  7. {
  8.     ui->setupUi(this);
  9.     m_oneSecTimer = new QTimer();
  10.     connect(m_oneSecTimer, SIGNAL(timeout()), this, SLOT(slotOneSec()));
  11.     m_time = QDateTime::currentDateTime();
  12.     m_oneSecTimer->start(1000);
  13.     ui->myTime->setText(m_time.toString("hh:mm:ss"));
  14.     ui->computerTime->setText(QDateTime::currentDateTime().toString("hh:mm:ss"));
  15. }
  16. Dialog::~Dialog()
  17. {
  18.     delete m_oneSecTimer;
  19.     delete ui;
  20. }
  21. void Dialog::slotOneSec()
  22. {
  23.     m_time = m_time.addSecs(1);
  24.     ui->myTime->setText(m_time.toString("hh:mm:ss"));
  25.     ui->computerTime->setText(QDateTime::currentDateTime().toString("hh:mm:ss"));
  26. }






离线dbzhang800

只看该作者 1楼 发表于: 2014-10-16
建议你在槽函数中加入一条输出语句,输出 当前时间(精确到ms)到终端或文件中。这样别人容易分析
离线yearl

只看该作者 2楼 发表于: 2014-10-16

上面是我计算出的时间。
下面是系统时间。
离线dbzhang800

只看该作者 3楼 发表于: 2014-10-16
你需要给出一系列的值出来,比如,从启动timer开始,直到2分钟结束,近120个值
离线yearl

只看该作者 4楼 发表于: 2014-10-16
好吧。我改一下。不过系统时间如何精确到ms?
离线dbzhang800

只看该作者 5楼 发表于: 2014-10-16
回 yearl 的帖子
yearl:好吧。我改一下。不过系统时间如何精确到ms? (2014-10-16 15:32) 

直接
qDebug()<<QDateTime::currentDateTime();

即可。 当然你可以用和你代码中一样使用toString()来更详细控制输出的字符串
离线roywillow

只看该作者 6楼 发表于: 2014-10-16
我记得Qt5的QTimer可以设置使用什么样精度的定时器
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线yearl

只看该作者 7楼 发表于: 2014-10-16
回 roywillow 的帖子
roywillow:我记得Qt5的QTimer可以设置使用什么样精度的定时器 (2014-10-16 16:43) 

文档说定时间隔小于20ms时使用精度更高的多媒体计时器。我试过了,设10ms,可还是没效果。
其实程序代码很简单,不会有问题。
只是QT定时器与XP系统定时器的关系究竟是怎样的?系统时钟是怎么处理的?为什么会出现这么大的差别?
离线roywillow

只看该作者 8楼 发表于: 2014-10-16
回 yearl 的帖子
yearl:文档说定时间隔小于20ms时使用精度更高的多媒体计时器。我试过了,设10ms,可还是没效果。
其实程序代码很简单,不会有问题。
只是QT定时器与XP系统定时器的关系究竟是怎样的?系统时钟是怎么处理的?为什么会出现这么大的差别? (2014-10-16 17:06) 

强制改一下timerType呢?
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线stlcours

只看该作者 9楼 发表于: 2014-10-17
回 yearl 的帖子
yearl:文档说定时间隔小于20ms时使用精度更高的多媒体计时器。我试过了,设10ms,可还是没效果。
其实程序代码很简单,不会有问题。
只是QT定时器与XP系统定时器的关系究竟是怎样的?系统时钟是怎么处理的?为什么会出现这么大的差别? (2014-10-16 17:06) 

注意啊,windows封装的时间其实是硬件中断,每次中断最低17ms,你设10ms当然没效果。高精度时间器只是说在OS层面具有优先权(因为timer消息级别很低的),使用的是多媒体时间器函数,保证以你设想的方式运行,但它本身不能更快。

你在主贴里说的更快我不知道你是什么意思,能再详细讲讲你的困惑吗?
离线yearl

只看该作者 10楼 发表于: 2014-10-27
回 stlcours 的帖子
stlcours:注意啊,windows封装的时间其实是硬件中断,每次中断最低17ms,你设10ms当然没效果。高精度时间器只是说在OS层面具有优先权(因为timer消息级别很低的),使用的是多媒体时间器函数,保证以你设想的方式运行,但它本身不能更快。
你在主贴里说的更快我不知道你是什么意思,能再 .. (2014-10-17 17:42) 

非常感谢回复。

是这样的:
程序中,
我设置了一个定时器。
获取系统时间。
启动这个定时器,每隔一秒钟在原系统时间上加一秒并显示。同时显示新获取的系统时间。
。。。。。。
过一段时间之后,这两个时间不一样了,差别越来越大。比如系统时间显示是10:43:42,而我计算出来的时间是11:03:35了。

QT4.8.4 winXP
可以确定系统时间是对的,我程序计算出来的时间快了。

同样的程序,在绝大部分电脑上没问题,只在个别电脑上有这个问题。如果是电脑主板方面的问题,那为什么系统时钟是对的呢?

这个问题是在一个实际程序中发现的,后来编了一个小程序将问题孤立出来了。
离线begboy

只看该作者 11楼 发表于: 2014-10-27
回 yearl 的帖子
yearl:文档说定时间隔小于20ms时使用精度更高的多媒体计时器。我试过了,设10ms,可还是没效果。
其实程序代码很简单,不会有问题。
只是QT定时器与XP系统定时器的关系究竟是怎样的?系统时钟是怎么处理的?为什么会出现这么大的差别? (2014-10-16 17:06) 

yearl,你好!
     如不涉及商业秘密,可否告知程序计时精度到什么程度?
是秒,毫秒,或更高的计时精度?
或者我们能帮上忙。

祝好运!
begboy
离线stlcours

只看该作者 12楼 发表于: 2014-10-27
回 yearl 的帖子
yearl:非常感谢回复。
是这样的:
程序中,
....... (2014-10-27 14:26) 

我想你的程序应该没问题。应该是那台电脑的问题。比如它装了什么程序,比如钩子,比如部分游戏自己控制时间,比如库损坏,也可能BIOS的问题。你至少应该让他重装XP再试试你的程序。
离线yearl

只看该作者 13楼 发表于: 2014-10-28
为什么XP系统的时钟(系统托盘里显示的时间)是对的呢?他采取了什么样的手段?
非常不解。
离线dbzhang800

只看该作者 14楼 发表于: 2014-10-28
回 yearl 的帖子
yearl:为什么XP系统的时钟(系统托盘里显示的时间)是对的呢?他采取了什么样的手段?
非常不解。
 (2014-10-28 14:10) 

其实我还是关心你的实验结果:

比如启动一个间隔1s的QTimer,连续记录120个槽函数被调用时的当前时间。

这样的一个完整的测试程序,也就10几行的代码量。
离线roywillow

只看该作者 15楼 发表于: 2014-10-28
实在不行用QTimeLine来代替QTimer呢?这个可以保证长期运行的稳定性,只要你设置足够长的时间,比如说24小时,一共24*60*60帧
注意设置一下easing curve
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线yearl

只看该作者 16楼 发表于: 2014-10-29
回 dbzhang800 的帖子
dbzhang800:其实我还是关心你的实验结果:
比如启动一个间隔1s的QTimer,连续记录120个槽函数被调用时的当前时间。
....... (2014-10-28 15:46) 

谢谢。回头我搞一下。
其实我的程序已经显示出来了,只是没有记录下来。
离线liudianwu

只看该作者 17楼 发表于: 2015-07-12
我也遇到类似问题,XP上完全正常,WIN7上会越来越慢!奇怪!
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线z55716368

只看该作者 18楼 发表于: 2015-07-14
又是这种只有头没有围的帖子
每一个问题 都是一次进步
离线圣域天子

只看该作者 19楼 发表于: 2015-07-14
QTimer 只是类似心跳包一样的计时触发器。
系统时间取自计算机中专用的时间CPU,它会自动纠正时间值。
没什么奇怪的,如果要做精确计时,当然需要取得系统时间,或者CPU开机后运行时间。
离线彩阳

只看该作者 20楼 发表于: 2015-07-15
除了QTimer外,还可以用QBasicTimer以及QObject::startTimer
这三者都对比一下,选择比较轻量的解决方案。
上海Qt开发联盟,热忱地欢迎你的加入!
快速回复
限100 字节
 
上一个 下一个