In an async program, the difference between
await task.Delay()
//and
thread.sleep
is nominal in a simple app, one might be more cancellable, one might be more accurate, one might be a tiny bit faster... but at the end of the day, both do the same thing, they block the executing code...
Here are the results:
1 00:00:00.0000767
Not Delayed.
1 00:00:00.2988809
Delayed 1 second.
4 00:00:01.3392148
Delayed 3 second.
5 00:00:03.3716776
Delayed 9 seconds.
5 00:00:09.3838139
Delayed 10 seconds
4 00:00:10.3411050
4 00:00:10.5313519
From this code:
var sw = new Stopwatch();
sw.Start();
Console.WriteLine($"{sw.Elapsed}");
var asyncTests = new AsyncTests();
var go1 = asyncTests.WriteWithSleep();
var go2 = asyncTests.WriteWithoutSleep();
await go1;
await go2;
sw.Stop();
Console.WriteLine($"{sw.Elapsed}");
Stopwatch sw1 = new Stopwatch();
Stopwatch sw = new Stopwatch();
public async Task WriteWithSleep()
{
sw.Start();
var delayedTask = Task.Delay(1000);
Console.WriteLine("Not Delayed.");
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {sw.Elapsed}");
await delayedTask;
Console.WriteLine("Delayed 1 second.");
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {sw.Elapsed}");
Thread.Sleep(9000);
Console.WriteLine("Delayed 10 seconds");
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {sw.Elapsed}");
sw.Stop();
}
public async Task WriteWithoutSleep()
{
await Task.Delay(3000);
Console.WriteLine("Delayed 3 second.");
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {sw.Elapsed}");
await Task.Delay(6000);
Console.WriteLine("Delayed 9 seconds.");
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {sw.Elapsed}");
}
Sleep acts the same way as an immediate await, except it blocks the thread. A task that is assigned to a var may cause a thread switch when it is finally awaited. In this example, it looks like the code starts on thread 1, then creates thread 5 for WriteWithoutSleep(), but continues executing on thread 1 for ThreadWithSleep() until delayedTask is awaited. At that moment, thread 1's code flows into thread 4 and further execution in Main is now on thread 4; thread 1 is for lack of a better word thrown away.
All of the above answers are very valuable. However, In a simple console app, it doesn't seem to matter except maybe academically over the course of several runs which you use if you immediately await your Task.Delay() and don't intend to use cancellation tokens;
In a complex app, putting threads to sleep vs. jumping from thread to thread due to creating tasks and awaiting them later vs. immediate awaits could be points of consideration.
Finally, putting a Process.GetCurrentProcess().Threads.Count at the beginning of a console app (at least mine) produced 13 threads in debugger mode. After the awaited calls, I had 17 threads in debugger mode in visual studio. I've read that ConsoleApps have only 3 threads and the rest are debugger threads, but running the consoleApp without debugging in visual studio resulted in 8 and then 14 threads. Running it outside visual studio resulted in 8 then 14 threads.
Copying the code and pasting it just afterwards had the same number of the threads, 8,14 and everything stayed on threads 4 and 5. The second thread.sleep and task.delays did not cause thread jumps. And all of this research is to propose: while thread.sleep will block a thread and task.delay will not and has a cancellation token, unless your app is pretty complex, it really doesn't matter as on the surface: task.delay and thread.sleep do pretty much the same thing.