Every n*x milliseconds I perform an action where n = 0, 1, 2, ...; x is some increment.
Example - every 25 milliseconds I perform a calculation.
This action can take fewer than x seconds for each increment. As a result, I need a way in C# to wait the remaining (x - actual_time) milliseconds.
Example - if the calculation only takes 20 milliseconds, I need to wait 5 more milliseconds before re-running the calculation.
Please advise.
Thanks, Kevin
That level of accuracy will be very difficult to achieve in a non real-time operating system like Windows. Your best bet might be to look into the multimedia timers.
The other .NET timers won't have the kind of resolution your need.
I presume that is C# running on Windows.
And there is your problem. Windows is not a "realtime" operating system.
The best you can do if you need millisecond-grade timing precision is to set the thread priority of your thread extremely high, and then busy-wait while querying the high performance timer (Stopwatch).
You cannot yield to another thread; the other thread could run for as much as 16 milliseconds before the operating system context switches it, and of course unless you are the highest priority thread, you have no guarantee that control is coming back to you after those 16 milliseconds are up.
Now, setting thread priority high and then busy waiting is one of the most rude things you can possibly do; essentially you will be taking control of the user's machine and not allowing them to do anything else with it.
Therefore what I would do is abandon this course of action entirely. Either, (1) consider obtaining an operating system designed for realtime process control if that is in fact your application, rather than an operating system designed for multitasking a bunch of line-of-business applications. Or (2) abandon your requirement that the action happen exactly every 25 milliseconds. Just perform the calculation once and yield the remainder of your quantum to another thread. When you get control back, see if more than 25 ms has passed since you yielded; if it has not, yield again. If it has, start over and perform the calculation.
At 25ms, you may be the wrong side of the resolution of your available timers in .Net.
However - as a general solution I'd probably attempt this a different way to your "do calculation..wait until 25ms has passed" approach.
A better way may well be to use a System.Timers.Timer, on a 25ms trigger, to trigger the calculation.
In the above example, a
DoCalc
method will be called every 25 ms (timer resolution issues notwithstanding). You would need to consider what to do if your calculation overran it's allotted time though. As it stands, the above code would allow a second calculation to start, even if the previous had not completed.This is a difficult one, and your options are fairly limited, as Eric Lippert and Matt Burland indicate. Basically, you can either
The latter solution will statistically give you a 40Hz timer in your sample use case, but you'll have significant jitter due to the low resolution of the timer you are using.
This is the tradeoff, the call is yours to make.
Here's a high-precision timer I wrote. I get roughly <1ms avg precision on 25ms interval. But if Windows is busy it may come in late. It's fairly lean on CPU utilization. Feel free to use. It uses Sleep(1) when the next tick is more than 15ms away and then SpinUntil (which yields as needed) to keep CPU usage at bay. Uses .NET4 features.
Link: High Precision Timer