I'm developing Windows 10 Universal App in C#/Xaml, I'm using await Task.Delay(delayInMilliseconds) to suspend a method for given time. My scenario is somewhat realtime, so it's very sensitive to time changes, and I need to make sure that when i suspend a method for let's say 8 millisecods it is suspended for 8 millisecods. I have noticed that the actual time span for which ** Task.Delay ** suspends the method differes from what is passed as delay parameter, for 1 up to 30 ms, the length of "deviation" being different in each call. So, when I want to sleep for 8 milliseconds, my system sleeps for 9 to 39 milliseconds, and this completly ruins my scenario. So, my question what is the best way to substitute ** Task.Delay ** and to achieve good precision? For the time being I use this method:
public static void Delay1(int delay)
{
long mt = delay * TimeSpan.TicksPerMillisecond;
Stopwatch s = Stopwatch.StarNew();
while (true)
{
if (s.Elapsed.TotalMilliseconds > delay)
{
return;
}
}
}
but it guees it consumes a lot of resources, that is 100% of a processor's core. If an user has small number of processor's cores, this would be very insufficient.
The Delay method is typically used to delay the operation of all or part of a task for a specified time interval. Most commonly, the time delay is introduced: At the beginning of the task, as the following example shows.
Task. Delay() is asynchronous. It doesn't block the current thread. You can still do other operations within current thread.
Delay acts in a very different way than Thread. Sleep. Basically, Task. Delay will create a task which will complete after a time delay.
You need to call Task. sleep() using await as it will cause the task to be suspended, and you also need to use try because sleep() will throw an error if the task is cancelled. Important: Calling Task. sleep() will make the current task sleep for at least the amount of time you ask, not exactly the time you ask.
According to msdn it's not possible to achieve more accuracy due to system clock resolution:
This method depends on the system clock. This means that the time delay will approximately equal the resolution of the system clock if the millisecondsDelay argument is less than the resolution of the system clock, which is approximately 15 milliseconds on Windows systems.
You should use multi-media timers. Those are much accurate. Take a look here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/2024e360-d45f-42a1-b818-da40f7d4264c/accurate-timer
Seems like I've found a sattisfactory solution:
new System.Threading.ManualResetEvent(false).WaitOne(delayInMilliseconds) instead of await Task.Delay(delayInMilliseconds);
I've used following code to test both methods:
async void Probe()
{
for (int i = 0; i < 1000; i++)
{
// METHOD 1
await Task.Delay(3);
// METHOD 2
new System.Threading.ManualResetEvent(false).WaitOne(3);
}
}
The code above should take exactly 3 seconds to execute. With METHOD 2 it took around 3300 ms, so the eror is 0.3 ms per call. Acceptable for me. But the METHOD 1 tok around 15 seconds (!) to execute which gives totally unacceptable error for my scenario. I only wonder what's the usage of CPU with Method 2, hope it doesn't use polling, the documentation says something about use of signals but unfortnatelly it doesn't automatically mean that polling isn't used spomewhere else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With