June 10th, 2020

How Do I Think About Async Code?!

Leslie Richardson
Program Manager

Increasingly essential to writing responsive applications, asynchronous code is becoming more and more popular. Unfortunately, asynchronous programming adds an additional level of complexity to your code.  As a result, understanding how this code even works can be tough no matter your experience level.  Whether you’re new to it or you just want a refresher, here is an intro to the world of asynchronous code!

 

What is asynchronous code?

Asynchronous (async) programming lets you execute a block of code without stopping (or blocking) the entire thread where the action is being executed.  A common myth about async code is that it improves performance, which isn’t necessarily true.  Instead, the major perk of async programming is that it increases the number of tasks (throughput) that can be executed concurrently without having to block the thread where these actions are taking place.

You may think async code seems a little like multithreaded code.  After all, many methods could be executing at the same time in both.  In reality, async programming can be used together with singular or multithreaded applications.  This means you can have a single-threaded async program, where one thread can run concurrent tasks.  Conversely, you can also have a multi-threaded async application, where multiple threads can each run multiple concurrent tasks.

 

Why should I use async code?  Example please!

To use an analogy to demonstrate async programming, consider the action of baking a cake. This action will be represented by a thread that is executing several steps (or tasks), as illustrated in code below.  This code is serviceable, and you will still have a yummy cake once the method is done executing.  However, since all the code is synchronous, each line will run sequentially.  In other words, you will be standing completely still while waiting for the oven to finish preheating.  You could be making the batter for your cake in the meantime!

Synchronous MakeCake() function
Synchronous MakeCake() function

 

Synchronous cake program
Synchronous cake program

 

In real life, you typically want to multitask by making the batter while the oven preheats or making the icing while the cake is baking.  Doing this increases your productivity and allows you to bake the cake much faster. This is where asynchronous code comes in handy!  By making our existing code asynchronous, we can perform more actions to pass the time even while we are awaiting a task like baking the cake in the oven to complete. To do this, we modified our code to include a new function called PassTheTime. This code saves a task’s state, starts running another synchronous or asynchronous function, and retrieves the saved task’s value when it’s actually needed.

Asynchronous MakeCake() function
Asynchronous MakeCake() function

 

Image AsyncCake Run
Asynchronous cake program

 

When compared to the synchronous MakeCake method that lacks a PassTheTime function call, MakeCakeAsync manages to complete more tasks without blocking the thread and shortens the time it takes to execute the whole method.

Async versus sync program comparison
Async versus sync program comparison

 

How do I write async code in .NET?

Thankfully, C# makes it a “piece of cake” to write asynchronous code with the Task type and the await and async keywords.  The Task type tells the caller about the eventual return value type. It also indicates that other actions can execute while the caller method is being processed.  The async keyword enables the await keyword, which lets the compiler know that we’ll need the return value of the function, but not right away.  As a result, we don’t need to block the call and can continue running other tasks until the awaited value is needed.  An async method will initially run synchronously until it hits an await keyword. This is when the asynchronous execution will begin.

 

I just learned about async code!  Now what?

While using async code to bake a cake is great, there are plenty of other real-life applications to use asynchronous code.  Two of the most common examples include:

  • Programs using HTTP requests – Depending on the request, HTTP calls can take a long time to fully process. Using async code can let you perform other work while waiting for the server to respond.

HTTP GET request example
HTTP GET request example

 

  • Programs using UI elements – WPF apps or any apps using buttons, textboxes, and other UX assets lend themselves well to async implementation. For instance, a WPF app taking in a file to be parsed may take a while.  By making this action async, you can still interact with the UI without having the app completely freeze as you wait for the function to complete.

Now that you know the basics of asynchronous programming, it’s time to improve on it!  There are a lot of secret do’s and don’ts when writing solid async code.  For a great resource that explores these tips and tricks, check out David Fowler’s post on async programming.

Like all code, there will come a time where you’ll need to diagnose bugs in your async program.  To learn how to debug your async code in Visual Studio, tune in for an upcoming blog post…

Side note: And no, I did not use the cake analogy just because I’ve been doing a lot of baking recently. 😉

Red velvet cupcake

Author

Leslie Richardson
Program Manager

Leslie is a Program Manager on the C# developer experience team, focusing primarily on improving the overall .NET and C# productivity experience and feature set.

20 comments

Discussion is closed. Login to edit/delete existing comments.

  • MURUGESAN MANOKARAN

    very nicely done (baked ..multi layered colorful cake)!!!

    can we introduce rating to these blogs and a search option at the top (advanced search …by author, date, technology…etc)? May be I dont know how to ??!!

  • Rob Kennedy

    I wanted to thank you for the article, but more importantly, thank you for your example code not having spaghetti returns all over the place. A single exit point is a beautiful thing. 🙂

  • John Akermanis

    Hi Leslie,

    Excellent post and an easy to understand example how Async works using the cake analogy. Best example I have come across.

    Cheers

    John

  • Jesse Dickey

    Wait, are you saying just calling an async method from an async method, actually causes the last method to start running asynchronously at that point, even if you don't actually await for it until later? That was the part of the code that was different from other examples, normally the await appears on the same line as the method call, instead of storing the return value in a Task variable. Are you sure Task is actually running before calling await on it later on? What if you don't await for it all? If you just want it to run and...

    Read more
  • Kim Homann

    Thank you!

  • Sam Smith

    Awesome, easy to understand example. Thanks for the source code too!

  • Nick

    Well done! This is perhaps the most succinct article/example of asynchronous coding I have read. Illustrating a simple and straightforward benefit of async/await is an extremely smart use of the reader’s time. Thank you, will be sharing this article with our other developers.

    Best,

    Nick

  • Anders Baumann

    Hi Leslie.
    Thanks for an interesting article. Good examples always improve understanding. For async, I think a better example than baking a cake is a restaurant with multiple waiters and chefs. In the synchronous solution, the waiter goes to the chef with an order. The waiter then waits in the kitchen for the food to be cooked. While he is waiting he cannot serve any other guests. In the async solution, the waiter goes to the kitchen with the order and then immediately returns to the tables to take other orders. The chef rings the bell when the food is...

    Read more
  • Vincent Thorn

    Async code, despite all this hype around, is not the thing you can push everywhere!

    First of all, not everywhere you need "quick responsibility". If you wanna HTML page, what the heck you need clicking on half-empty page?? First wait until it's loaded and THEN interact. Same with many operations: when you save a document, WAIT - make SURE it's safe and then continue work. Esp. when you work with slow media. Esp. when Windows behaves like slowpoke on simplistic operations (because of dirt architecture).

    Second, async code makes code more complex and harder to debug. Read: "makes code error prone". I...

    Read more
    • Mike

      Vincent, you are correct. The "follow the herd mentality" has lead coders to believe that Async coding is some sort of revolution. Even the example given above (baking cake) is technically not correct. The making pizza example given by people on other sites is also not correct. Here is why......

      When you turn an oven on, and go on to do other things (say, making icing); somebody or something has to be heating the oven. Yes, the real-life-oven is an appliance, but something is going on inside that heats it - consumption of electricity, the moving...

      Read more
  • Erik Bongers

    “An async method will initially run synchronously until it hits an await keyword.”
    That sounds as if first PreheatTask is run and THEN ingredients are added and THEN preheat result is retrieved asynchronously.

    In fact (I think) the opposite happens: main function and preheat function run ASYNCHRONOUSLY until AWAIT forces them to sync up again.

    (I think I read somewhere that the compiler splits an async function into an initial synchronous block…but that’s irrelevant in this introduction and causes confusion)