Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to introduce an accurate small delay in a task without CPU overload? [duplicate]

I am implementing a communication algorithm to send information periodically and very fast, i.e. 1ms between packs. I've a functional version that uses Tasks to send the packs. Here an example of my code:

private void Work()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    while (!cancellationTokenSource.Token.IsCancellationRequested)
    {
        if (!Pack.PeriodicOn)
            cancellationTokenSource.Cancel();

        // Time used to send the packs before the interval time
        double tolerance = Pack.Interval * 0.2F;

        // In case of interval bigger than 25ms send pasks only 5ms before
        if (tolerance > 5) tolerance = 5;

        TimeSpan timeSpan = stopwatch.Elapsed;

        // The waiting time is controlled by the condition below, if the condition is false, the while loop continues execution         
        // Send the information a little bit before to interval time to deal with the transmision delay
        if (Pack.LastSent.TotalMilliseconds == 0 ||
             timeSpan.TotalMilliseconds - Pack.LastSent.TotalMilliseconds >=
             (Pack.Interval - tolerance))
        {
            SendData(Pack);
            Pack.LastSent = timeSpan;
        }
    }

    Pack.LastSent = new TimeSpan(0);
}

My problem relies in the fact that the CPU usage increases to an undesirable levels. I know that I can avoid that by introducing some delay, but, Thread.Sleep(1) is very inaccurate and the real transmission interval between packs rises, if I use await Task.Delay(1) seems to produce the same effect.

Does anybody have an alternative way to introduce, accurately, delay in tasks?

Thanks in advance!

like image 801
YRod Avatar asked Dec 21 '16 22:12

YRod


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 create a new thread?

Task. Delay does not create new Thread, but still may be heavy, and no guaranties on order of execution or being precise about deadlines.

Does task delay block thread?

Delay(1000) doesn't block the thread, unlike Task. Delay(1000).

What is the wait command in C#?

Introduction to C# Wait C # wait is defined as waits for the task to finish its execution. It sources the current thread to wait until another thread calls its notify() or notifyAll() methods.


1 Answers

How to introduce an accurate small [1ms] delay without CPU overload [on Windows]?

You can't, sorry. The system scheduler on windows is only slightly adjustable (by selecting Adjust for best performance of Applications in the advanced system properties dialog for Windows Server or setting a registry value), but it won't go into sub-millisecond territory. If it did, the performance of the entire system would suffer unacceptably.

Depending on your hardware, I think it might be possible to reduce the system clock resolution as low as 0.5ms; however, the minimum thread quantum you can set is 6, which would require two clock ticks to reduce to 0. So you'd still end up with a quantum of 1ms, which is at least twice as slow as you'd need. And, of course, you'd reduce your battery life by ~15% (from what I've read).

For more information, read Windows Internals.

like image 111
Stephen Cleary Avatar answered Sep 29 '22 02:09

Stephen Cleary