1

In C# I have an example:

public async static Task TaskTest(int i)
{
    await Task.Delay(1);
    Console.WriteLine($"{i}. {DateTime.Now.ToString("HH:mm:ss fff")} " +
        $"ThreadId:{Thread.CurrentThread.ManagedThreadId} Start");

    int count = 1;
    while (true)
    {
        DoSomeThing(count);

        var stopWatch = new Stopwatch();
        stopWatch.Start();

        await Task.Delay(100);

        stopWatch.Stop();
        if (stopWatch.Elapsed.TotalMilliseconds > 200)
            Console.ForegroundColor = ConsoleColor.Red;

        Console.WriteLine($"Id:{count} Time:{DateTime.Now.ToString("HH:mm:ss fff")} " +
         $"ThreadID:{Thread.CurrentThread.ManagedThreadId} Time Delay:{stopWatch.Elapsed.TotalMilliseconds }");

        Console.ForegroundColor = ConsoleColor.White;
        count++;
    }
}

public async static Task DoSomeThing(int index)
{
    await Task.Delay(1);
    Task.Delay(1000).Wait();
}

private static void Main(string[] args)
{
    int i = 1;
    while (i < 2)
    {
        TaskTest(i);
        Task.Delay(1).Wait();
        i++;
    }
    Console.ReadKey();
}

Here is my result Result

Id:8 Time:23:03:59 972 ThreadID:12 Time Delay:582.6348

Id:22 Time:23:04:01 974 ThreadID:14 Time Delay:552.7234000000001

Id:42 Time:23:04:04 967 ThreadID:8 Time Delay:907.3214

I don't know why Task sometimes delay more than 200 milliseconds.

Update: Thank for all answer. I update my code to use Thread and Thread.Sleep() and Task.Run(). I increase number of Threads run forever to 500. I tested in 30 minutes and 500 threads never sleep more than 200ms. Do you think that is bad code? Please leave a comment! Thank you so much!

public static void TaskTest(object i)
{
    Console.WriteLine($"{i} Start");

    int count = 1;
    while (true)
    {
        // Open Task to do work
        Task.Run(() => { DoSomeThing(count); });

        var stopWatch = new Stopwatch();
        stopWatch.Start();

        Thread.Sleep(100);

        stopWatch.Stop();
        if (stopWatch.Elapsed.TotalMilliseconds > 200)
        {
            Console.WriteLine($"Id:{count} Time:{DateTime.Now.ToString("HH:mm:ss fff")} " +
            $"ThreadID:{Thread.CurrentThread.ManagedThreadId} Time Delay:{stopWatch.Elapsed.TotalMilliseconds }");
        }

        count++;
    }
}

public static void DoSomeThing(int index)
{
    Thread.Sleep(1000); // Time spent complete work
}

private static void Main(string[] args)
{
    int i = 0;
    while (i < 500)
    {
        // Open Thread for TaskTest
        Thread tesThread = new Thread(TaskTest);
        tesThread.IsBackground = true;
        tesThread.Start(i);
        i++;
    }

    Console.WriteLine("Finish init");
    Console.ReadKey();
}
tad
  • 11
  • 2
  • 3
    `Task.Delay(100)` will wait *at least* 100ms. There is no guarantee when the scheduler will get around to running the continuation after your await. – GazTheDestroyer Aug 12 '20 at 16:30
  • 3
    You have a mix of [fire and forgets](https://stackoverflow.com/q/46053175/11683) and [blocking calls](https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html) (to `Wait`). The result is hardly surprising. – GSerg Aug 12 '20 at 16:32
  • 2
    Basically your question is "if I try to push system to the point it breaks it does indeed break. Why is that?" - Creating large number of async operations will indeed require large amount of time to process them, just handling returns alone can take long time... – Alexei Levenkov Aug 12 '20 at 16:33
  • The `DoSomeThing` is an asynchronous method (you should add the [Async](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap#naming-parameters-and-return-types) suffix in its name btw), but you are not awaiting it. Why? – Theodor Zoulias Aug 12 '20 at 18:38

1 Answers1

7

Task.Delay, like any other multi-threaded sleep function, yields the thread it's running on back to the system (or in the case of the thread pool, back to the thread pool scheduler), asking to be re-scheduled some time after the amount of time specified.

That is the only guarantee you have, that it will wait at least the amount specified. How long it will actually wait heavily depends on your thread pool load (you're delaying an awful lot of tasks there), general system load (there's thousands of threads at any given point in time to be scheduled on an average computer OS) and on your CPU&OS's capability to schedule threads quickly (in Windows, look at timeBeginPeriod).

Long story short, if precise timing matters to you, don't relinquish your thread.

Blindy
  • 65,249
  • 10
  • 91
  • 131