This site uses cookies to deliver our services and to show you relevant ads and job listings.
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
Your use of Stack Overflow’s Products and Services, including the Stack Overflow Network, is subject to these policies and terms.

Join us in building a kind, collaborative learning community via our updated
Code of Conduct.

Also, in your example notice that you get a warning when you compile the code above. Pay attention to the warning. It is telling you that this code doesn't make sense.
– Eric LippertNov 14 '13 at 19:14

"Shouldn't it be reached immediately?": No. Your DoSomethingAsync() method shall yield control to its caller when it is waiting for a long job! (usually with another await keyword in its code!)
– S.SerpJul 11 at 8:03

18 Answers
18

When using async and await the compiler generates a state machine in the background.

Here's an example on which I hope I can explain some of the high-level details that are going on:

public async Task MyMethodAsync()
{
Task<int> longRunningTask = LongRunningOperationAsync();
// independent work which doesn't need the result of LongRunningOperationAsync can be done here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
await Task.Delay(1000); // 1 second delay
return 1;
}

Independent work is done on let's assume the Main Thread (Thread ID = 1) then await longRunningTask is reached.

Now, if the longRunningTask hasn't finished and it is still running, MyMethodAsync() will return to its calling method, thus the main thread doesn't get blocked. When the longRunningTask is done then a thread from the ThreadPool (can be any thread) will return to MyMethodAsync() in its previous context and continue execution (in this case printing the result to the console).

A second case would be that the longRunningTask has already finished its execution and the result is available. When reaching the await longRunningTask we already have the result so the code will continue executing on the very same thread. (in this case printing result to console). Of course this is not the case for the above example, where there's a Task.Delay(1000) involved.

@BenisonSam thread is a bit old, but I had the same question and have been looking for an answer. Reason for the "await" is that if we omit the "await" the LongRunningOperationAsync() will return immediately. In fact the compiler will give a warning if we remove the await. Stephen Cleary's blog post blog.stephencleary.com/2011/09/… gives an execellent of the design discussions.
– shev72Dec 4 '15 at 10:33

32

If every async method need to have an await inside of it, and a await can only be done on a methods with async, when does it stop?
– Bruno SantosMay 19 '16 at 13:46

50

This answer is clearly wrong. These many upvotes will cause wrong understanding to many users. MS documentation clearly says, no other thread is used when just using async, await. msdn.microsoft.com/en-us/library/mt674882.aspx Please somebody correct the answer. Due to this i wasted one whole day.
– Krishna DeepakAug 15 '16 at 23:35

and more specifically at the example included, it explains your situation a bit

The following Windows Forms example illustrates the use of await in an
async method, WaitAsynchronouslyAsync. Contrast the behavior of that
method with the behavior of WaitSynchronously. Without an await
operator applied to a task, WaitSynchronously runs synchronously
despite the use of the async modifier in its definition and a call to
Thread.Sleep in its body.

thanks for the answer. But is WaitAsynchronouslyAsync() executed on a separate thread?
– Dan DinuJan 22 '13 at 9:51

22

I do belive so, from the section An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
– Adriaan StanderJan 22 '13 at 9:56

8

According to this MSDN article, "The async and await keywords don't cause additional threads to be created.... an async method doesn't run on its own thread". My understanding is that at await keywords the framework skips ahead (back to the caller) to allow all possible independent code to run while waiting for long operations to finish. I think that means that once all independent code has run, if the long operation hasn't returned, it will block. I am just learning this now, though.
– VimesApr 12 '13 at 19:49

8

@astander That is incorrect. It does not execute on a different thread. It is just schedules the continuation (the rest of the method) to be called when the timer used by Task.Delay fires.
– MgSamNov 14 '13 at 19:02

1

This answer is wrong because of the Sleep. See the accepted answer with await Task.Delay(1000); which has the correct behavior.
– Jared UpdikeFeb 28 '14 at 23:25

So it's not running on a background thread, but it also doesn't block. This is possible due to asynchronous API's which use callbacks instead of juggling with threads. You initiate an (I/O, socket, ..) operation and return to doing your things. When the operation is done, the OS will invoke the callback. This is what Node.js or the Python Twisted framework does and they have some nice explanation, too.
– Roman PlášilAug 18 '13 at 16:59

1

"The async keyword enables the await keyword. So any method using await must be marked async.", - but why? this answer doesn't help to understand why the method must be marked as async. Can't the compiler just infer that the method is async by looking inside for await keywords?
– StanislavJan 14 '14 at 15:07

Suggested clarification: No, because async methods are not run on another thread by default. In your example, the Sleep() call within DoSomethingAsync() blocks the current thread which prevents execution from continuing within button1_Click() until DoSomethingAsync() completes. Note that while Thread.Sleep() blocks the executing thread, Task.Delay() does not.
– DavidRRMay 27 '16 at 19:11

Explanation

Here is a quick example of async/await at a high level. There are a lot more details to consider beyond this.

Note: Task.Delay(1000) simulates doing work for 1 second. I think it's best to think of this as waiting for a response from an external resource. Since our code is waiting for a response, the system can set the running task off to the side and come back to it once it's finished. Meanwhile, it can do some other work on that thread.

In the example below, the first block is doing exactly that. It starts all the tasks immediately (the Task.Delay lines) and sets them off to the side. The code will pause on the await a line until the 1 second delay is done before going to the next line. Since b, c, d, and e all started executing at almost the exact same time as a (due to lack of the await), they should finish at roughly the same time in this case.

In the example below, the second block is starting a task and waiting for it to finish (that is what await does) before starting the subsequent tasks. Each iteration of this takes 1 second. The await is pausing the program and waiting for the result before continuing. This is the main difference between the first and second blocks.

Extra info regarding SynchronizationContext

Note: This is where things get a little foggy for me, so if I'm wrong on anything, please correct me and I will update the answer. It's important to have a basic understanding of how this works but you can get by without being an expert on it as long as you never use ConfigureAwait(false), although you will likely lose out on some opportunity for optimization, I assume.

There is one aspect of this which makes the async/await concept somewhat trickier to grasp. That's the fact that in this example, this is all happening on the same thread (or at least what appears to be the same thread in regards to its SynchronizationContext). By default, await will restore the synchronization context of the original thread that it was running on. For example, in ASP.NET you have an HttpContext which is tied to a thread when a request comes in. This context contains things specific to the original Http request such as the original Request object which has things like language, IP address, headers, etc. If you switch threads halfway through processing something, you could potentially end up trying to pull information out of this object on a different HttpContext which could be disastrous. If you know you won't be using the context for anything, you can choose to "not care" about it. This basically allows your code to run on a separate thread without bringing the context around with it.

How do you achieve this? By default, the await a; code actually is making an assumption that you DO want to capture and restore the context:

await a; //Same as the line below
await a.ConfigureAwait(true);

If you want to allow the main code to continue on a new thread without the original context, you simply use false instead of true so it knows it doesn't need to restore the context.

await a.ConfigureAwait(false);

After the program is done being paused, it will continue potentially on an entirely different thread with a different context. This is where the performance improvement would come from -- it could continue on on any available thread without having to restore the original context it started with.

Is this stuff confusing? Hell yeah! Can you figure it out? Probably! Once you have a grasp of the concepts, then move on to Stephen Cleary's explanations which tend to be geared more toward someone with a technical understanding of async/await already.

The most useful example I have found in hours! Thanks
– RSFalcon7Jun 1 '17 at 18:40

Lets say if all these task are returning a int and if I am using first task's result in second task(or some calculation) It would be wrong?
– veerendra guptaJun 9 '17 at 7:41

3

@veerendragupta yes. You would consciously choose not to run them asynchronously in that case (because they're not asynchronous). There are also a few other things to realize regarding configuration context which I won't go into here
– Joe PhillipsJun 9 '17 at 12:48

2

@Jocie Not quite. When you call await, I think it releases the thread back to the pool instead of holding it. This makes it available for use elsewhere while awaiting the return of the Task
– Joe PhillipsJan 24 at 15:33

2

@JoePhillips I think what you just said is the essence of async/await. The calling thread is freed and can be used by other processes on the machine. When the await call is complete, a new thread is used to resume what the caller originally started. The caller is still waiting, but the benefit is that a thread is freed in the meantime. That's the benefit of async/wait?
– Bob HornMar 11 at 15:26

Here is a quick console program to make it clear to those who follow. The "TaskToDo" method is your long running method that you want to make async. Making it run Async is done by the TestAsync method. The test loops method just runs through the "TaskToDo" tasks and runs them Async. You can see that in the results because they don't complete in the same order from run to run - they are reporting to the console UI thread when they complete. Simplistic, but I think the simplistic examples bring out the core of the pattern better than more involved examples:

In web applications that sees a large number of concurrent requests at
start-up or has a bursty load (where concurrency increases suddenly),
making these web service calls asynchronous will increase the
responsiveness of your application. An asynchronous request takes the
same amount of time to process as a synchronous request. For example,
if a request makes a web service call that requires two seconds to
complete, the request takes two seconds whether it is performed
synchronously or asynchronously. However, during an asynchronous call,
a thread is not blocked from responding to other requests while it
waits for the first request to complete. Therefore, asynchronous
requests prevent request queuing and thread pool growth when there are
many concurrent requests that invoke long-running operations.

The basic idea is that you have a separate pool of threads that execute tasks asynchronously. When using it. The object does however make the promise that it will execute the operation at some time and give you the result when you request it. This means that it will block when you request the result and hasn't finished, but execute in the thread pool otherwise.

From there you can optimize things: some operations can be implemented async and you can optimize things like file IO and network communication by batching together subsequent requests and/or reordering them. I'm not sure if this is already in the task framework of Microsoft - but if it isn't that would be one of the first things I would add.

You can actually implement the future pattern sort-of with yields in C# 4.0. If you want to know how it works exactly, I can recommend this link that does a decent job: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . However, if you start toying with it yourself, you will notice that you really need language support if you want to do all the cool things -- which is exactly what Microsoft did.

See this fiddle https://dotnetfiddle.net/VhZdLU (and improve it if possible) for running a simple console application which shows usages of Task, Task.WaitAll(), async and await operators in the same program.

This fiddle should clear your execution cycle concept.

Here is the sample code

using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
var a = MyMethodAsync(); //Task started for Execution and immediately goes to Line 19 of the code. Cursor will come back as soon as await operator is met
Console.WriteLine("Cursor Moved to Next Line Without Waiting for MyMethodAsync() completion");
Console.WriteLine("Now Waiting for Task to be Finished");
Task.WaitAll(a); //Now Waiting
Console.WriteLine("Exiting CommandLine");
}
public static async Task MyMethodAsync()
{
Task<int> longRunningTask = LongRunningOperation();
// independent work which doesn't need the result of LongRunningOperationAsync can be done here
Console.WriteLine("Independent Works of now executes in MyMethodAsync()");
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine("Result of LongRunningOperation() is " + result);
}
public static async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
Console.WriteLine("LongRunningOperation() Started");
await Task.Delay(2000); // 2 second delay
Console.WriteLine("LongRunningOperation() Finished after 2 Seconds");
return 1;
}
}

public static void Main(string[] args)
{
string result = DownloadContentAsync().Result;
Console.ReadKey();
}
// You use the async keyword to mark a method for asynchronous operations.
// The "async" modifier simply starts synchronously the current thread.
// What it does is enable the method to be split into multiple pieces.
// The boundaries of these pieces are marked with the await keyword.
public static async Task<string> DownloadContentAsync()// By convention, the method name ends with "Async
{
using (HttpClient client = new HttpClient())
{
// When you use the await keyword, the compiler generates the code that checks if the asynchronous operation is finished.
// If it is already finished, the method continues to run synchronously.
// If not completed, the state machine will connect a continuation method that must be executed WHEN the Task is completed.
// Http request example.
// (In this example I can set the milliseconds after "sleep=")
String result = await client.GetStringAsync("http://httpstat.us/200?sleep=1000");
Console.WriteLine(result);
// After completing the result response, the state machine will continue to synchronously execute the other processes.
return result;
}
}

The way I understand it is also, there should be a third term added to the mix: Task.

Async is just a qualifier you put on your method to say it's an asynchronous method.

Task is the return of the async function. It executes asynchronously.

You await a Task. When code execution reaches this line, control jumps out back to caller of your surrounding original function.

If instead, you assign the return of an async function (ie Task) to a variable, when code execution reaches this line, it just continues past that line in the surrounding function while the Task executes asynchronously.

The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread. The method runs on the current
synchronization context and uses time on the thread only when the
method is active.

In the following code, the HttpClient method GetByteArrayAsync returns a Task, getContentsTask. The task is a promise to produce the actual byte array when the task is complete. The await operator is applied to getContentsTask to suspend execution in SumPageSizesAsync until getContentsTask is complete. In the meantime, control is returned to the caller of SumPageSizesAsync. When getContentsTask is finished, the await expression evaluates to a byte array.

private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}

The answers here are useful as a general guidance about await/async. They also contain some detail about how await/async is wired. I would like to share some practical experience with you that you should know before using this design pattern.

The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing. On the foreground thread, this is a disaster. The foreground thread carries the burden of constructing your app, including views, view models, initial animations, and whatever else you have boot-strapped with those elements. So when you await the foreground thread, you stop the app. The user waits and waits when nothing appears to happen. This provides a negative user experience.

You can certainly await a background thread using a variety of means:

Device.BeginInvokeOnMainThread(async () => { await AnyAwaitableMethod(); });
// Notice that we do not await the following call,
// as that would tie it to the foreground thread.
try
{
Task.Run(async () => { await AnyAwaitableMethod(); });
}
catch
{}

The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing. This is not true - maybe you meant Task.Wait()? When you use await, it sets the rest of the method as a continuation to be executed when whatever you await-ed is complete. It exits the method that you used it in, so the caller can continue. Then when the await-ed line is actually complete, it finishes the remainder of that method on some thread (usually a worker thread).
– mmcraeJul 1 at 20:41

@geometrikal at the very core, async/await is about freeing up .NET Threads. When you await a truly-async operation (such as .NET's File.WriteAsync), it suspends the remainder of the method you used await in, so the caller can continue and potentially finish its purpose. There is no thread blocking or waiting for the await-ed operation. When the operation you awaited is complete, the remainder of the async/await method is put on a thread and executed (similar to a call-back idea).
– mmcraeJul 1 at 20:47

1) Async keyword enables the await and that's all it does. Async keyword does not run the method in a separate thread. The beginning f async method runs synchronously until it hits await on a time-consuming task.

2) You can await on a method that returns Task or Task of type T. You cannot await on async void method.

3) The moment main thread encounters await on time-consuming task or when the actual work is started, the main thread returns to the caller of the current method.

4) If the main thread sees await on a task that is still executing, it doesn't wait for it and returns to the caller of the current method. In this way, the application remains responsive.

5) Await on processing task, will now execute on a separate thread from the thread pool.

6) When this await task is completed, all the code below it will be executed by the separate thread