Profile picture
Nick Craver @Nick_Craver
, 10 tweets, 3 min read Read on Twitter
I'm seeing a lot of confusion around Task.Delay(). While not apparent, it's important to know that this:
await Task.Delay(1);
does not wait 1 millisecond. Most of the time it'll wait at least 16 and possibly longer. There are 2 things in play here...
When you await a task, what happens is that task runs, and then after it runs, the rest of your method does. The task and the work after must be run by *something*, that's the thread pool. It has to have a thread available to do that, and it must be scheduled for it to happen.
Also, the Task.Delay() is at the mercy of timer resolution itself, that's generally 16ms. That's why you're not going to get that 1ms your expect. Then, after it completes, that next unit of work (called the continuation) has to be scheduled a run. Is a thread free? Maybe!
If a thread isn't available, well it gets to park in the Task queue and wait until one is. So in a busy application, your delay can be indefinitely longer than what you have specified. Specific delays and async just do not play well, due to this shared queue.
It's easy to test this yourself! Here's a super simple program only doing the delay...and a gist so you can tinker: gist.github.com/NickCraver/3df…
As for the "why?". It boils down to processors. CPUs still aren't that power efficient *except when they're sleeping*. A lot of power efficiency comes from batching work together, waking up, doing it fast, then sleeping for as long as possible. OS makers call this "alignment".
If your CPU is constantly waking (and going to a higher frequency as a result, in most machine's default configuration these days), it's eating a lot more power to do so. And since most things don't need < 15-16ms resolution...it's what they do by default.
Games and other media bits that need high res timers can kick the timer resolution up to 1ms (or even lower), but this comes at a power and CPU utilization cost because updating those OS tick counts isn't free. Life is full of trade-offs, this is one of 'em.
Anyway, hope that helps you somewhere down the road! Always be aware of these timing and queue bits with Task when designing and debugging. The Task API hides a lot of complexity, but knowing a bit about a few basics underneath can go a long way...as with most things in life.
Oh, it's worth noting: when I say "most of the time", that's due to how continuations work and where .Delay() is often used. The initial await (say at the top level of a simple program) will be in the 1-16ms range, catching the first timer interval. Like this:
Missing some Tweet in this thread?
You can try to force a refresh.

Like this thread? Get email updates or save it to PDF!

Subscribe to Nick Craver
Profile picture

Get real-time email alerts when new unrolls are available from this author!

This content may be removed anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member and get exclusive features!

Premium member ($3.00/month or $30.00/year)

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!