Bald Bearded Builder
csharp/you-should-probably-stop-using-task-wait-in-csharp

You Should Probably Stop Using Task.Wait in C#

EF Core's `AsSplitQuery` avoids Cartesian explosion by loading sibling relationships with separate SQL queries and combining the results.

Loads from YouTube when you press play

Transcript 2 topics

Avoid Task.Wait

0:00

Are you thinking of using task dot wait to write asynchronous code? Well, stop. There's a better way. Let's start with how an operating system works, specifically processes and threads. We build applications that compile into commands that run on process.

Those processes are made of threads, and processes have a limited number of threads that they can use to run our commands. Code that reserves a thread and then holds it until it's completely finished is called blocking code. Typically we see this with CPU or IO intensive commands. CPU intensive commands include things like image or video compression or even complex mathematical computation. For IO intensive commands, you're looking at things like database reads and writes or web requests or even reading and writing from the file system.

Blocking code is a bad thing and we should write code that releases threads as quickly as possible. So let's look at an asynchronous method using Task. Wait. In this code, we're gonna write the ID of the thread we're on to the console. Then we're gonna create a new task that waits five seconds before returning.

Then we're gonna call the wait method on that task and once it finishes running, we'll write the ID of the thread we're on to the console again. When we run this code, you can see that the thread we're on before we waited and after are the same. Is that a coincidence? Nope. Because task.

Wait does not release the thread while it's waiting. We've already talked about not wanting to do that. So what's a better way to write asynchronous code? Introducing the await operator.

Await instead

1:27

Let's refactor that code a little bit. We'll remove the task. Wait and replace it with await task. Voila! Our code ran and we can see that it actually finished on a different thread than it started with.

Why did that happen? Because when that process began to wait for our task to complete, it freed up that thread to be used by others who may need it. And then once our operation was finished, it gave us a free thread that we could use to finish up. Now the thread that it gave us could have been the same one we had before, but we certainly can't count on that. And it's best for us to stand back and let the thread pool do that voodoo that it do.

So there you have it. Unless you're getting way down in the weeds on threading, let's leave the task dot wait alone and stick with the await operator. Until next time!

Sign in to join in. Reading needs nothing.