3

I would like to know if a QTimer will keep on counting once it has timed out.

For example, let's say I have a QTimer that times out every 500ms. Let's say when this particular QTimer times out, my program happens to be in some function that I have made (not in the event loop) and it takes 10ms for the program to get from my function, to the event loop. Does that mean that the next time the QTimer times out will be at 1010ms?

If this is the case, is there a way to get around it?

Thanks.

Edit: Timer results

Jean-Luc
  • 3,563
  • 8
  • 40
  • 78

2 Answers2

2

When you put a Qtimer with delay d, it will fire a timeout() signal after this period of time is elapsed and as soon as all the events in the window system's event queue have been processed.

So if your program spend whatever time not in the event loop then it is fine. Anyway whether in Qt or not, setting a timeout to t ms really means, wake me up when at least t ms have passed. You cannot guarantee exactitude whatsoever.

ps: If you are worried about few ms then you should be worried about the timing granularity.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • Hi, Thanks for your answer. My problem is, I have 4 QTimers running at once, and somehow, the 500ms timer is always out by around 10ms. The problem is though, that it is out by ~8s cumulative. So after two timeouts, the time is really ~1016ms and over a long period of time, this is really bad. I have no idea how this could happen. – Jean-Luc Apr 04 '12 at 12:51
  • Are you on windows? Does it happens if you run your program on a different platform? – UmNyobe Apr 04 '12 at 13:33
1

I made some test using multiple timers but with timerEvent (QObject::setTimer()).

The thing is, of course if you have multiple timers that interfere at some point (tick exactly in the same time) all your doStuffThatTake10ms code will be 'queued' ... But the absolute precision of timers should remain over time. Here some code to try it out.

#ifndef MULTITIMER_H
#define MULTITIMER_H

#include <QObject>
#include <QTime>

class MultiTimer : public QObject
{
    Q_OBJECT
public:
    explicit MultiTimer(QObject *parent = 0);
    void timerEvent(QTimerEvent *event);

private:
    int timerId[4];
    int interval[4];
    int count[4];
    QTime absoluteTimer;
};

#endif // MULTITIMER_H

Implementation .cpp

#include "MultiTimer.h"
#include <QTimerEvent>
#include <QTime>
#include <QDebug>

MultiTimer::MultiTimer(QObject *parent) :
    QObject(parent)
{
    interval[0] = 500;
    interval[1] = 1000;
    interval[2] = 1500;
    interval[3] = 2000;

    for( int i = 0; i < 4; i++)
        timerId[i] = startTimer(interval[i]);

    for( int i = 0; i < 4; i++)
        count[i] = 0;

    absoluteTimer.start();
}

void MultiTimer::timerEvent(QTimerEvent *event)
{
    int id = -1;
    for( int i = 0; i < 4; i++){
        if( event->timerId() == timerId[i]){
            id = i;
            count[id]++;
            break;
        }
    }

    if( id != -1) {
        qDebug() << "timer" << id
                 << "interval" << interval[id]
                 << "count" << count[id]
                 << "total" << count[id]*interval[id]
                 << "reference" << absoluteTimer.elapsed();

        usleep(10000);
    }
}

To try it out create a = QApllication() and a MultiTimer object and fire a.exec().

Result after 1 minute on linux

timer 1 interval 1000 count 59 total 59000 reference 59010 
timer 0 interval 500 count 119 total 59500 reference 59500 
timer 0 interval 500 count 120 total 60000 reference 60000 
timer 1 interval 1000 count 60 total 60000 reference 60010 
timer 3 interval 2000 count 30 total 60000 reference 60021 
timer 2 interval 1500 count 40 total 60000 reference 60031 
timer 0 interval 500 count 121 total 60500 reference 60500 

As you can see the 121th tick of timer 0 is right on time at 60500ms ... but at 60000ms all timers collide creating delayed execution.

Thomas Vincent
  • 2,214
  • 4
  • 17
  • 25
  • Thank you for your test code. I've run the test on my computer (Windows 7 x64) and have found the my timer results do indeed get worse over timer. If you take a look at my edit, you can see that by looking just at the 500ms, it reads later and later... By the last one shown there, it is almost 200ms out from when it started. I'm not surprised that linux does it a lot more accurately! P.S. To run it on windows, I had to change usleep(10000) to Sleep(10). I hope this didn't mess anything up. – Jean-Luc Apr 06 '12 at 02:48