How Does Async Works in C#

How does await async work in C#

MSDN explains everything.

I understand though that sometimes vanilla docs (particularly from MSDN) can be difficult to apply to your particular situation, so let's go over your points.

Question # 1: Is this assumption correct or the code below the await keyword is still executed?

The code below the "await" keyword will only be executed when the async call completes. In the meantime, since your method is marked "async", control will be returned to the caller of your method until your method completes.
From the MSDN link above:

Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();

// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;

I think the comments are quite explanatory.

Secondly suppose I called a service method async and need to return its result. The return statement is below the await keyword.

Question # 2: When is the return statement hit, after the async call has completed or before it?

After.

Question # 3: I want to use the result of that service call and async operation wont help cause I want the calling method to be hit when the result has been returned. I understand this can be done using the Result property which makes the call synchronus. But then what is the use of async in DB operations cause they are the ones that actually take 80% of the time in most apps.

Suppose you need to make three unrelated DB queries to complete your service, then perform a calculation based on the results, then finish. If you did this sequentially, you'd have to wait until each operation completes. If you use async calls, then C# will run the three queries in parallel and your service might finish much sooner.

Also, operations that return Task can be used as Futures. See MSDN on Futures where several patterns are discussed on how to parallelize work based on futures and merge the results.

If your service only needs one DB call then it will definitely be worse for you to call it async.

Question # 4: How can I use async with DB operations? Is it possible and recomended?

ADO.NET now includes async methods ReadAsync and NextResultAsync .

It is definitely possible, as for recommended this discussion is much more complete than I could write here.

Question # 5: In which scenraio will async operations be useful it seems that every api is just making async operations now without a reason? or did I miss the point of using async ops?

async operations are very useful to easily parallelize any long running operations without running into threading problems. If your method only does one thing, or a sequence of simple (fast) things, then yes it is useless to go async. However if you have more than one long running operations, it is far easier and less error prone to parallelize them via async than it is to do it managing threads.

How Async and Await works

I have an async intro on my blog that you may find helpful.

This code:

int result = await LongRunningOperation();

is essentially the same as this code:

Task<int> resultTask = LongRunningOperation();
int result = await resultTask;

So, yes, LongRunningOperation is invoked directly by that method.

When the await operator is passed an already-completed task, it will extract the result and continue executing the method (synchronously).

When the await operator is passed an incomplete task (e.g., the task returned by LongRunningOperation will not be complete), then by default await will capture the current context and return an incomplete task from the method.

Later, when the await task completes, the remainder of the method is scheduled to run in that context.

This "context" is SynchronizationContext.Current unless it is null, in which case it is TaskScheduler.Current. If you're running this in a Console app, then the context is usually the thread pool context, so the async method will resume executing on a thread pool thread. However, if you execute the same method on a UI thread, then the context is a UI context and the async method will resume executing on the UI thread.

How does async works in C#?

It works similarly to the yield return keyword in C# 2.0.

An asynchronous method is not actually an ordinary sequential method. It is compiled into a state machine (an object) with some state (local variables are turned into fields of the object). Each block of code between two uses of await is one "step" of the state machine.

This means that when the method starts, it just runs the first step and then the state machine returns and schedules some work to be done - when the work is done, it will run the next step of the state machine. For example this code:

async Task Demo() { 
var v1 = foo();
var v2 = await bar();
more(v1, v2);
}

Would be translated to something like:

class _Demo {
int _v1, _v2;
int _state = 0;
Task<int> _await1;
public void Step() {
switch(this._state) {
case 0:
this._v1 = foo();
this._await1 = bar();
// When the async operation completes, it will call this method
this._state = 1;
op.SetContinuation(Step);
case 1:
this._v2 = this._await1.Result; // Get the result of the operation
more(this._v1, this._v2);
}
}

The important part is that it just uses the SetContinuation method to specify that when the operation completes, it should call the Step method again (and the method knows that it should run the second bit of the original code using the _state field). You can easily imagine that the SetContinuation would be something like btn.Click += Step, which would run completely on a single thread.

The asynchronous programming model in C# is very close to F# asynchronous workflows (in fact, it is essentially the same thing, aside from some technical details), and writing reactive single-threaded GUI applications using async is quite an interesting area - at least I think so - see for example this article (maybe I should write a C# version now :-)).

The translation is similar to iterators (and yield return) and in fact, it was possible to use iterators to implement asynchronous programming in C# earlier. I wrote an article about that a while ago - and I think it can still give you some insight on how the translation works.

How and when to use ‘async’ and ‘await’

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;
}

OK, so what happens here:

  1. Task<int> longRunningTask = LongRunningOperationAsync(); starts executing LongRunningOperation

  2. 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.

Async/Await in Javascript vs C#

I am not familiar with JavaScript but this statement:

Async/await makes your code look synchronous, and in a way it makes it
behave more synchronously. The await keyword blocks execution of all
the code that follows it until the promise fulfills, exactly as it
would with a synchronous operation.

Sounds pretty much applicable to C# async/await. For both cases your code looks like you execute it synchronously and your execution is sequential. Because in C# when you have code like this:

// ...
await FooAsync();
Console.WriteLine("Await has returned the execution");

It seems as if your execution thread were running FooAsync, and then, the same thread is calling Console.WriteLine. Whereas in reality when the execution thread hits await, it does lots of things behind the scene. Here's a good article about it. But in most of the cases,

When the await keyword is applied, it suspends the calling method and
yields control back to its caller until the awaited task is complete.

The thread that were executing your code will go about his business. And then proceed with Console.WriteLine when FooAsync is complete by another (or the same) thread.
This behavior is enormously helpful when you work with UI threads like in WPF or WinForms applications.
For example, FooAsync is a very heavy method. It does lots of calculations and takes a lot of time to complete. But you're running your code on UI and when a user hits a button, the underlying code is executed by the UI thread. So if you'll be running and waiting FooAsync synchronously like this:

FooAsync().Result;

Your UI would be "freezed" and the user would demise you.
So when you go

await FooAsync();

UI thread "asks" TaskScheduler to run FooAsync by whatever available thread. After the Task is completed, TaskScheduler tries to execute next line:

Console.WriteLine("Await has returned the execution");

by the UI thread again,

exactly as it would with a synchronous operation.

can anyone help me understand await/async implementation in c#

When compiling your code, you should have received warnings that gave you a hint what was wrong:

warning CS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

An async method will run synchronously until it reaches the first await expression where the value it's awaiting isn't already completed.

In your case, all your async methods return completed tasks - Method1Async and Method2Async will simply run synchronously, then return a completed task, which means that CallMethodAsync will await those already-completed tasks, and itself complete synchronously.

If you add something like await Task.Yield() in Method1Async and Method2Async, then you'll see genuine asynchronous behavior: those methods will return incomplete tasks (when they reach Task.Yield) which means CallMethodAsync itself will return an incomplete tasks, etc.

C# - understanding async/await

Because you're calling await on HashAsync the control will be yielded to the caller, which is this case is .NET Framework itself, which called your Main method.

I think the easiest way to see how this works would be to assign the Task returned from HashAsync to a variable but not await it until after the Console.WriteLine:

private static async Task Main(string[] args)
{
Task<string> resultTask = HashAsync(Guid.NewGuid().ToByteArray(), 4);

Console.WriteLine("Calculating hash...");'

string result = await resultTask;

Console.WriteLine(result);

Console.Read();
}

With this change, once you call into HashAsync it will push work to the background using Task.Run and return you a Task to observe progress of that work. But because you're not awaiting it Main method will continue executing and Calculating hash... will be printed. Only once you call await resultTask control will be returned to whoever called Main and execution will be suspended.

How does Async programming work with Threads when using thread.sleep()?

I see no evidence of multithreading background threads. What am I missing?

Possibly you are looking in the wrong place, or using the wrong tools. There's a handy property that might be of use to you, in the form of Thread.CurrentThread.ManagedThreadId. According to the docs,

A thread's ManagedThreadId property value serves to uniquely identify that thread within its process.

The value of the ManagedThreadId property does not vary over time

This means that all code running on the same thread will always see the same ManagedThreadId value. If you sprinkle some extra WriteLines into your code, you'll be able to see that your tasks may run on several different threads during their lifetimes. It is even entirely possible for some async applications to have all their tasks run on the same thread, though you probably won't see that behaviour in your code under normal circumstances.

Here's some example output from my machine, not guaranteed to be the same on yours, nor is it necessarily going to be the same output on successive runs of the same application.

00:00:00.0000030
* WriteWithSleep on thread 1 before await
* WriteWithoutSleep on thread 1 before first await
* WriteWithSleep on thread 4 after await
Delayed 1 seconds
00:00:01.0203244
* WriteWithoutSleep on thread 5 after first await
Delayed 3 second.
00:00:03.0310891
* WriteWithoutSleep on thread 6 after second await
Delayed 9 seconds.
00:00:09.0609263
Delayed 10 seconds
00:00:10.0257838
00:00:10.0898976

The business of running tasks on threads is handled by a TaskScheduler. You could write one that forces code to be single threaded, but that's not often a useful thing to do. The default scheduler uses a threadpool, and as such tasks can be run on a number of different threads.

understanding Async and Await in C#

Asynchronous is not concurrent. Each call to await will prevent the code following from being executed until the Task has completed. In this case, you can create concurrency by changing your example to look like this

class Program
{
static void Main()
{
new Content().Print().Wait();
Console.Read();
}
}

class Content
{

public async Task<string> Delay1()
{
await Task.Delay(5000);
return "hello";
}
public async Task<string> Delay2()
{
await Task.Delay(5000);
return "hello";
}
public async Task<string> Delay3()
{
await Task.Delay(5000);
return "hello";
}

public async Task Print()
{
var tasks = new[] {Delay1(), Delay2(), Delay3()};
await Task.WhenAll(tasks);
foreach(var result in tasks.Select(x => x.Result))
{
Console.WriteLine(result);
}
}
}

You can start three Tasks independently of one another and store them in a collection. Then, you can call await Task.WhenAll to block execution until all of those tasks have completed. Afterwards, you can loop through the results and use them however you want.



Related Topics



Leave a reply



Submit