How Do I Think About Async Code?!

Leslie Richardson


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


Leave a comment

  • Avatar
    Ion Sorin Torjo

    Hi Leslie,

    Yes, C# does make it insanely easy to use async.

    Having said that, and you’re in the VS team, can you please tell us when will the following be available:

    * Speed up UWP compile times – it’s simply insane building non-trivial UWP apps. Compile times are to the roof! MS has known about this for years.
    * Being able to see the async stack trace in UWP. Losing the initial context is makes it really hard to debug UWP apps.



  • Avatar
    Neil MacMullen

    Hi Leslie – nice article and a good “real world” example of async! I think the wording around the “PassTheTime” explanation is a little confusing (at least for me!) since it implies that “PassTheTime” is handling the asynchrony and state restoration rather than the “await” – you kind of skipped over the crucial point that the async methods run until they hit a blocking operation so by making the operations async you’re really changing the semantics to be “StartBakingTheCake” etc. (Obvious if you already know it but seems like your article is aimed at beginners to async who might take some time to figure this out.)

    BTW – there is a very nice library called TaskTupleAwaiter ( that introduces a nice syntax for this kind of “just run a few arbitrary async things in parallel”. To my eye the visual presentation it allows..

    await (PrepareIngredientsAsync,PreheadOvenAsync) ; 

    makes it more obvious that these things are being done together compared to placing them on sequential lines.

  • Avatar
    Rick Leitch

    I enjoyed the article Leslie. I’ve always been curious… Most code examples on MSDN await every task immediately. Even the out-of-box new project Visual Studio templates await every task immediately. Isn’t this the same as synchronous programming? Why use asynchronous keywords in these cases? To achieve asynchronous behavior I’ve always done what you’ve done here. I assign the task to a variable, and await it later. I look forward to your comments.

    • Avatar

      When you await the task depends on when you need the result, but since the typical case is that we make the async call and want to use the result immediately it’s simpler and cleaner to just write var someResult = await DoWorkAsync();.

      The real magic of async/await it that it looks like synchronous code, but what’s happening is that when you call your DoWorkAsync() method it returns a Task instead of just returning a synchronous result.

      If that task isn’t Completed when execution reaches the await then, instead of the executing thread blocking as would happen in synchronous code, the thread returns to the thread pool and is free to pick up other work. When DoWorkAsync() completes a free thread will resume execution at the statement following the await.

      So where you put the await doesn’t make your code synchronous. You simply await the task at the point you want the result. For tasks that don’t return results you can think of the result as being ‘the task has completed’, generally for its side effects.

      This is why the async/await pattern mostly applies to IO calls where the thread that would otherwise be blocked can go and do useful work during the few milliseconds the IO takes, and that means we can service potentially thousands of IO calls with one or a few threads.

  • Алексей Кайгородов
    Алексей Кайгородов

    there are two kinds of parallel activities: threads and tasks. Asynchronous program is a parallel program which employs tasks (and, most likely, threads). Any parallel program can be implemented in both ways. The advantage of tasks is less memory consumption, because they do not have attached stack. The disatwantage is more complex programming: the work of a single thread often requires more than one tasks. Besides, programmer must not allow their tasks to perform bloking operations.

  • Avatar

    Any ideas where can I download the code to create the app as shown in your blog? I just want to get started so the best thing is to see how this code was created.

    Want to compare with parallel processing but your code looks very efficient.


  • Avatar
    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)

  • Vincent Thorn
    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 rather pay for RELIABLE code than “fast written”. MS thinks different and that’s why we have “cr**ppy quality” of Win10.

    Stop the hype, we all already know what async is. No more push, leave us alone and let decide when WE need that feature.

  • Anders Baumann
    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 ready and the waiter picks up the food and brings it to the guests.


  • Avatar

    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.