开发者

Problem with waitable timers in Windows (timeSetEvent and CreateTimerQueueTimer)

开发者 https://www.devze.com 2022-12-24 07:24 出处:网络
I need high-resolution (more accurate than 1 millisecond) timing in my application.The waitable timers in Windows are (or can be made) accurate to the millisecond, but if I need a precise periodicity

I need high-resolution (more accurate than 1 millisecond) timing in my application. The waitable timers in Windows are (or can be made) accurate to the millisecond, but if I need a precise periodicity of, say, 35.7142857141 milliseconds, even a waitable timer with a 36 ms period will drift out of sync quickly.

My "solution" to this problem (in ironic quotes because it's not working quite right) is to use a series of one-shot timers where I use the expiration of each timer to call the next timer. Normally a process like this would be subject to cumulative error over time, but in each timer callback I check the current time (with System.Diagnostics.Stopwatch) and use this to calculate what the period of the next timer needs to be (so if a timer happens to expire a little late, the next timer will automagically have a shorter period to compensate).

This works as expected, except that after maybe 10-15 seconds the timer system seems to get bogged down, and a few timer callbacks here and there arrive anywhere from 25 to 100 milliseconds late. After a couple of seconds the problem goes away and everything runs smoothly again for 10-15 seconds, and then the stuttering again.

Since I'm using Stopwatch to set each timer period, I'm also using it to monitor the arrival times of each timer callback. During the smooth-running periods, most (maybe 95%) of the intervals are either 35 or 36 milliseconds, and no intervals are ever more than 5 milliseconds away from the expected 35.7142857143.

During the "glitchy" stretches, the distribution of intervals is very nearly identical, except that a very small number are unusually large (a couple more 开发者_JS百科than 60 ms and one or two longer than 100 ms during maybe a 3-second stretch). This stuttering is very noticeable, and it's what I'm trying to fix, if possible.

For the high-resolution timer, I was using the extremely antique timeSetEvent() multimedia timer from winmm.dll. In pursuit of this problem, I switched to using CreateTimerQueueTimer (along with timeBeginPeriod to set the high-resolution), but I'm seeing the same problem with both timer mechanisms. I've tried experimenting with the various flags for CreateTimerQueueTimer which determine which thread the timer runs on, but the stuttering appears no matter what.

Is this just a fundamental problem with using timers in this way (i.e. using each one-shot timer to call the next)? If so, do I have any alternatives? One thing I was considering was to determine how many consecutive 1-millisecond-accuracy ticks would keep my within some arbitrary precision limit before I need to reset the timer. So, for example, if I wanted a 35.71428 period, I could let a 36 ms timer elapse 15 times before it was off by 5 milliseconds, then kill it and start a new one.


Given limitations in .NET, I think you have a good approach. What is your process priority? I'm thinking it needs to be higher than normal to avoid other processes doing disk activity.

I agree with Henk that the .NET framework is not the best solution here. If garbage collection occurs, it may take a while to free objects, compact the heap, etc.

What OS are you using? I also agree with Henk that a real-time OS is the best solution. According to what I've read, Windows CE qualifies as a real-time OS, but I can't really comment further.


Timers aren't cheap and by using a 1ms timer to approach a 35.7 one you are eating away at your margins here. I think you may be at the limit of what can be achieved on the PC itself.
I would go for a longer period timer (35 or 36) and correction with the stopwatch timer.

And to start some controversy, I'm not so sure the .NET framework is the most suitable platform for this kind of task. Have you thought of how the GC fits in with your demands?

0

精彩评论

暂无评论...
验证码 换一张
取 消