Are there good rule(s) for when to use Task.Delay versus Thread.Sleep?
- Specifically, is there a minimum value to provide for one to be effective/efficient over the other?
- Lastly, since Task.Delay causes context-switching on a async/await state machine, is there an overhead of using it?
Use Thread.Sleep
when you want to block the current thread.
Use Task.Delay
when you want a logical delay without blocking the current thread.
Efficiency should not be a paramount concern with these methods. Their primary real-world use is as retry timers for I/O operations, which are on the order of seconds rather than milliseconds.
The biggest difference between Task.Delay
and Thread.Sleep
is that Task.Delay
is intended to run asynchronous. It does not make sense to use Task.Delay
in synchronous code. It is a VERY bad idea to use Thread.Sleep
in asynchronous code.
Normally you will call Task.Delay()
with the await
keyword:
await Task.Delay(5000);
or, if you want to run some code before the delay:
var sw = new Stopwatch();
sw.Start();
Task wait = Task.Delay(5000);
Console.WriteLine(\"async: Running for {0} seconds\", sw.Elapsed.TotalSeconds);
await wait;
Guess what this will print? Running for 0.0070048 seconds.
If we move the await wait
above the Console.WriteLine
instead, it will print Running for 5.0020168 seconds.
Let\'s look at the difference with Thread.Sleep
:
class Program
{
static void Main(string[] args)
{
Task wait = asyncTask();
syncCode();
wait.Wait();
Console.ReadLine();
}
static async Task asyncTask()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine(\"async: Starting\");
Task wait = Task.Delay(5000);
Console.WriteLine(\"async: Running for {0} seconds\", sw.Elapsed.TotalSeconds);
await wait;
Console.WriteLine(\"async: Running for {0} seconds\", sw.Elapsed.TotalSeconds);
Console.WriteLine(\"async: Done\");
}
static void syncCode()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine(\"sync: Starting\");
Thread.Sleep(5000);
Console.WriteLine(\"sync: Running for {0} seconds\", sw.Elapsed.TotalSeconds);
Console.WriteLine(\"sync: Done\");
}
}
Try to predict what this will print...
async: Starting
async: Running for 0.0070048 seconds
sync: Starting
async: Running for 5.0119008 seconds
async: Done
sync: Running for 5.0020168 seconds
sync: Done
Also, it is interesting to notice that Thread.Sleep
is far more accurate, ms accuracy is not really a problem, while Task.Delay
can take 15-30ms minimal. The overhead on both functions is minimal compared to the ms accuracy they have (use Stopwatch
Class if you need something more accurate). Thread.Sleep
still ties up your Thread, Task.Delay
release it to do other work while you wait.
if the current thread is killed and you use Thread.Sleep
and it is executing then you might get a ThreadAbortException
.
With Task.Delay
you can always provide a cancellation token and gracefully kill it. Thats one reason I would choose Task.Delay
. see http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx
I also agree efficiency is not paramount in this case.
I want to add something.
Actually, Task.Delay
is a timer based wait mechanism. If you look at the source you would find a reference to a Timer
class which is responsible for the delay. On the other hand Thread.Sleep
actually makes current thread to sleep, that way you are just blocking and wasting one thread. In async programming model you should always use Task.Delay()
if you want something(continuation) happen after some delay.