In this MSDN article, the following example code is provided (slightly edited for brevity):

public async Task<ActionResult> Details(int? id)
    if (id == null)
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

    Department department = await db.Departments.FindAsync(id);

    if (department == null)
        return HttpNotFound();

    return View(department);

The FindAsync method retrieves a Department object by its ID, and returns a Task<Department>. Then the department is immediately checked to see if it is null. As I understand it, asking for the Task's value in this manner will block code execution until the value from the awaited method is returned, effectively making this a synchronous call.

Why would you ever do this? Wouldn't it be simpler to just call the synchronous method Find(id), if you're going to immediately block anyway?

  • It could be implementation related. ... else return null; Then you'd need to check that the method actually found the department you asked for. Aug 11, 2016 at 20:10
  • I don't see any in an asp.net, but in a destop app, by doing it this way you are not freezing the ui
    – Rémi
    Aug 11, 2016 at 20:15
  • Here's a link that explain the await concept from the designer...msdn.microsoft.com/en-us/magazine/hh456401.aspx
    – Jon Raynor
    Aug 11, 2016 at 20:35
  • Await is only worth thinking about with ASP.NET if thread contact switches are slowing you down, or the memory usage form many threads stacks is an issue for you.
    – Ian
    Nov 9, 2016 at 13:58

6 Answers 6


As I understand it, asking for the Task's value in this manner will block code execution until the value from the awaited method is returned, effectively making this a synchronous call.

Not quite.

When you call await db.Departments.FindAsync(id) the task is sent off and the current thread is returned to the pool for use by other operations. The flow of execution is blocked (as it would be regardless of using department right after, if I understand things correctly), but the thread itself is free to be used by other things while you wait for the operation to be completed off-machine (and signalled by an event or completion port).

If you called d.Departments.Find(id) then the thread does sit there and wait for the response, even though most of the processing is being done on the DB.

You're effectively freeing up CPU resources when disk bound.

  • 3
    But I thought all await did was sign on the remainder of the method as a continuation on the same thread (there are exceptions; some async methods spin up their own thread), or sign on the async method as a continuation on the same thread and allow the remaining code to execute (as you can see, I'm not crystal-clear on how async works). What you're describing sounds more like a sophisticated form of Thread.Sleep(untilReturnValueAvailable) Aug 11, 2016 at 20:16
  • 3
    @RobertHarvey - it does assign it as a continuation, but once you've sent the task (and its continuation) off to be processed, there's nothing left to run. It's not guaranteed to be on the same thread unless you specify it (via ConfigureAwait iirc).
    – Telastyn
    Aug 11, 2016 at 20:21
  • 2
    See my answer...the continuation is marshalled back to the original thread by default. Aug 11, 2016 at 20:24
  • 3
    I think I see what I'm missing here. In order for this to provide any benefit, the ASP.NET MVC framework must await its call to public async Task<ActionResult> Details(int? id). Otherwise, the original call will just block, waiting for department == null to resolve. Aug 11, 2016 at 20:29
  • 3
    @RobertHarvey By the time await ... "returns" the FindAsync call has finished. That's what await does. It's called await because it makes your code wait for things. (But note that is not the same as making the current thread wait for things)
    – user253751
    Aug 11, 2016 at 23:27

I really hate that none of the examples show how it’s possible to wait a few lines before awaiting the task. Consider this.

Foo foo = await getFoo();
Bar bar = await getBar();

Console.WriteLine(“Do some other stuff to prepare.”);

doStuff(foo, bar);

This is the kind of code the examples encourage, and you’re right. There’s little sense in this. It does free the main thread to do other things, like respond to UI input, but the real power of async/await is I can easily keep doing other things while I’m waiting for a potentially long running task to complete. The code above will “block” and wait to execute the print line until we’ve gotten Foo & Bar. There’s no need to wait though. We can process that while we wait.

Task<Foo> foo = getFoo();
Task<Bar> bar = getBar();

Console.WriteLine(“Do some other stuff to prepare.”);

doStuff(await foo, await bar);

Now, with the rewritten code, we don’t stop and wait for our values until we have to. I’m always on the lookout for these kinds of opportunities. Being smart about when we await can lead to significant performance improvements. We’ve got multiple cores these days, might as well use them.

  • 3
    Hm, that's less about cores / threads and more about using asynchronous calls properly. Aug 5, 2018 at 12:48
  • You’re not wrong @Deduplicator. That’s why I quoted “block” in my answer. It’s hard to speak to this stuff without mentioning threads, but while still acknowledging there may or may not be multi-threading involved.
    – RubberDuck
    Aug 5, 2018 at 13:00
  • I suggest you be careful with awaiting inside another method call.. Sometimes compiler misunderstands this await and you get a really weird exception. After all async/await is just syntax sugar, you can check with sharplab.io how the generated code looks. I observed this on several occasions and now I just await one line above the call where result is needed... don't need those headaches. Mar 5, 2019 at 15:23
  • 3
    "There’s little sense in this." - There's lots of sense in this. The cases where "keep doing other things" is applicable in the very same method are not that common; it's far more common that you just want to await and let the thread do completely different things instead. Sep 4, 2019 at 6:31
  • When I said “there’s little sense in this” @SebastianRedl, I meant the case where you could obviously run both both tasks in parallel rather than run, wait, run, wait. This is far more common than you seem to think it is. I bet if you looked around your code base you’d find opportunities.
    – RubberDuck
    Sep 4, 2019 at 10:25

So there's more that happens behind the scenes here. Async/Await is syntactic sugar. First look at the signature of the FindAsync function. It returns a Task. Already you're seeing the magic of the keyword, it unboxes that Task into a Department.

The calling function does not block. What happens is that the assignment to department and everything following the await keyword get boxed into a closure and for all intents and purposes passed to the Task.ContinueWith method (the FindAsync function is automatically executed on a different thread).

Of course there is more that happens behind the scenes because the operation is marshalled back to the original thread (so you no longer have to worry about synchronizing with the UI when performing a background operation) and in the case of the calling function being Async (and being called asynchronously) the same thing happens up the stack.

So what happens is you get the magic of Async operations, without the pitfalls.


No it's not returning immediately. The await makes the method call asynchronous. When FindAsync is called, the Details method returns with a task which is not finished. When FindAsync finishes, it will return its result into the department variable and resume the rest of the Details method.

  • No there is no blocking at all. It will never get to department == null until after the async method is already finished.
    – Steve
    Aug 11, 2016 at 20:12
  • 1
    async await doesn't generally create new threads, and even if it did, you still need to wait for that department value to find out if it's null. Aug 11, 2016 at 20:18
  • 2
    So basically what you're saying is that, in order for this to be of any benefit at all, the call to public async Task<ActionResult> must also be awaited. Aug 11, 2016 at 20:25
  • 2
    @RobertHarvey Yes, you've got the idea. Async/Await is essentially viral. If you "await" one function, you should also await any functions that call it. await shouldn't be mixed with .Wait() or .Result, as this can cause deadlocks. The async/await chain typically ends at a function with an async void signature, which is mostly used for event handlers, or for functions invoked directly by UI elements.
    – KChaloux
    Aug 12, 2016 at 12:50
  • 1
    @Steve - "... so it would be on its own thread." No, read Tasks are still not threads and async is not parallel. This includes actual output demonstrating that a new thread is not created. Jun 27, 2018 at 4:58

I like to think of "async" like a contract, a contract that says "i can execute this asynchronously if you need it to, but you can call me like any other synchronous function as well".

Meaning, one developer was making functions and some design decisions led them to make/mark a bunch of functions as "async". The caller/consumer of the functions is at the liberty to use them as they decide. As you say you can either call await right before the function call and wait for it, this way you have treated it like a synchronous function, but if you wanted to, you can call it without await as

Task<Department> deptTask = db.Departments.FindAsync(id);

and after, say, 10 lines down the function you call

Department d = await deptTask;

hence treating it as an asynchronous function.

Its upto you.

  • 1
    It's more like "I reserve the right to handle the message asynchronously, use this for getting the result". Aug 5, 2018 at 12:52
  • Awaiting immediately is not really a synchronous call, if you do that on say an UI thread you will remain responsive. This is a synchronous (and dangerous) call Department d = db.Departments.FindAsync(id).Result; and it will cause the UI to freeze until it returns. (Be warned that using .Result like that can introduce dead-locks and should almost always be avoided unless you know the task is actually done.)
    – AnorZaken
    Mar 30, 2020 at 16:00

"if you're going to immediately block anyway" the anwser is "Yes". Only when you need a fast response, await/async make sense. For example UI thread come to a really async method, UI thread will return and continue to listen to button click, while code below "await" will be excuted by other thread and finally get the result.

  • 1
    What does this answer provide that the other answers don't?
    – user53019
    Sep 4, 2019 at 2:14

Not the answer you're looking for? Browse other questions tagged or ask your own question.