1

I have an application, written with Qt 4.8, that uses Qt's timer facilities to trigger periodic events at regular intervals (via QObject::startTimer(), with events posted to the owning QThread's message queue). Qt sets up timers on Windows by ultimately calling the Windows API function SetTimer.

The default resolution on Windows is 15.6ms. I need a period of 20ms +/- 0.5ms. However, when I specify 20ms, I am actually getting 31.2ms (+/- 0.02ms). When I specify 10ms (just for kicks), I am getting 15.6ms. This is all consistent with the default resolution. I need the resolution to be some factor of 19.5-20.5 (e.g. 0.5, 1, 2, 4, 5, 10, even 20).

I tried using timeBeginPeriod/timeEndPeriod, which reported success, but had no effect - I think this only applies to winmm timers and not SetTimer.

Qt timers are at the mercy of the underlying timer resolution for the platform, so I do have to go over its head.

Is there some way I can set the resolution of SetTimer? I'm OK with making Windows-specific API calls. I'm also OK with doing it globally, even if it comes down to a registry hack. The application is running on a dedicated Windows 7 machine, and system-wide negative effects of changing the timer resolution globally are inconsequential.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • I almost wonder if I should ask this on SU instead... – Jason C Jul 07 '14 at 02:11
  • It turns out `SetTimer` cannot be set for a period less than **10ms** http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx – Randy the Dev Jul 07 '14 at 03:27
  • @AndrewDunn Yeah; I've clarified my question even further. I actually need a period of 19.5-20.5ms, which I can't achieve with the 15.6ms resolution. – Jason C Jul 07 '14 at 03:47
  • Are you running an optimized build? You could be getting overhead – Randy the Dev Jul 07 '14 at 04:11
  • @AndrewDunn I am. I also am seeing the same results in a minimal test program that just starts a periodic timer and prints the time deltas (using the performance counter). It is very consistent with the 15.6ms default resolution; I am seeing multiples of 15.6ms +/- 0.02ms. – Jason C Jul 07 '14 at 04:13

2 Answers2

2

It is impossible to use a resolution less than 10ms using SetTimer. If you try to use a lower value, Windows will simply use 10ms instead.

Have you considered using the QElapsedTimer instead? It uses Windows' high resolution performance counter by default and falls back to a less precise timer if not available.

http://qt-project.org/doc/qt-4.8/qelapsedtimer.html

Randy the Dev
  • 25,810
  • 6
  • 43
  • 54
  • Thanks; the `QElapsedTimer` resolution is sufficient but I am actually using the timers to trigger periodic events, and the application is designed to handle timer events posted to the owner `QThread`'s message queue. Unfortunately, to minimize the damage I'd have to create a new thread to manage timing and do a bit of refactoring that I'd like to avoid (and if I do that I might as well just use winmm timers so I don't burn CPU looping). I've edited my question to clarify that I'm driving periodic events rather than measuring elapsed time. – Jason C Jul 07 '14 at 03:05
  • 1
    I don't know about Qt, but this is false / obsolete when it comes to Win7+. [A simple test proves that it can go down to 1ms](http://stackoverflow.com/a/4962857/33080). – Roman Starkov Oct 17 '16 at 02:06
1

From the Qt documentation about QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer) :

Note that QTimer's accuracy depends on the underlying operating system and hardware. The timerType argument allows you to customize the accuracy of the timer. See Qt::TimerType for information on the different timer types. Most platforms support an accuracy of 20 milliseconds; some provide more. If Qt is unable to deliver the requested number of timer events, it will silently discard some.

I think that you can set timer type to Qt::PreciseTimer. On Windows, Qt will use Windows's Multimedia timer facility (if available) for this type which has a resolution of 1 millisecond.

Nejat
  • 31,784
  • 12
  • 106
  • 138
  • Alas, I am using Qt 4.8, and the timer precision appears to be a new feature of Qt 5. This is certainly a compelling reason to upgrade though; it's good to see they addressed it. Thanks for pointing this out I would have had no idea it existed. – Jason C Jul 07 '14 at 05:36
  • Accepting this old answer because I upgraded away from Qt4 long ago and Qt5 has much more capable timer facilities. – Jason C Sep 05 '21 at 20:53