Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accuracy of Task.Delay

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.

like image 816
xcoder37 Avatar asked Jul 31 '15 09:07

xcoder37


People also ask

What is Task delay?

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.

Does task delay block?

Task. Delay() is asynchronous. It doesn't block the current thread. You can still do other operations within current thread.

Is Task delay the same as thread sleep?

Delay acts in a very different way than Thread. Sleep. Basically, Task. Delay will create a task which will complete after a time delay.

How do I make my task sleep?

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.


3 Answers

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.

like image 121
w.b Avatar answered Sep 23 '22 21:09

w.b


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

like image 39
ZDS Alpha Avatar answered Sep 24 '22 21:09

ZDS Alpha


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.

like image 37
xcoder37 Avatar answered Sep 24 '22 21:09

xcoder37