Await and Async usage - c#

The MSDN documentation for await and async gives the following simple example.
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
It then states:
If AccessTheWebAsync doesn't have any work that it can do between
calling GetStringAsync and awaiting its completion, you can simplify
your code by calling and awaiting in the following single statement.
string urlContents = await client.GetStringAsync();
But if there is no work to be done between calling the method and its completion what are the benefits of making this method asynchronous?

The await keyword means that the Thread starting the GetStringAsync method may become free during the execution of that method.
So for example let's say this is a web-server (e.g. with 10 threads in a thread-pool, which are responsible for processing the requests). In that case between the beginning of the GetStringAsync call and it's finish that thread is free to do other stuff.
Meaning even with 10 thread you can serve more then 10 users on a very effective way. If there would be no await in your code (and GetStringAsync would not be async, but a blocking synchronous method) and 11 users would access it at the same time then one of them would have trouble, since there would be no free thread to process the 11. request.
If that call would be a blocking synchronous code then the execution would just stay there and do nothing while your network card would just wait for the HTTP response from the server. So basically with "await" you avoid threads which are just waiting and do nothing.

When you await an async method, the thread is freed to do other work. In the synchronous version, that thread would have been blocked.

In general Async-Await consumes lesser threads, improves scalability by reducing memory/thread usage.
It also improves responsiveness as compared to synchronous code.
check Advantages of Async-Await

Related

Can this "Synchronous" Code Cause Deadlocks?

My company has a Nuget Package they wrote that can do various common tasks easily for you. One of which is making HTTP requests. Normally I always make my HTTP requests asynchronous, however in this Nuget package is the following code:
protected T GetRequest<T>(string requestUri)
{
// Call the async method within a task to run it synchronously
return Task.Run(() => GetRequestAsync<T>(requestUri)).Result;
}
Which calls this function:
protected async Task<T> GetRequestAsync<T>(string requestUri)
{
// Set up the uri and the client
string uri = ParseUri(requestUri);
var client = ConfigureClient();
// Call the web api
var response = await client.GetAsync(uri);
// Process the response
return await ProcessResponse<T>(response);
}
My question is, is this code really running synchronously by just wrapping the GetRequestAsync(requestUri) inside a Task.Run and calling .Result on the returned task? This seems like a deadlock waiting to happen, and we are seeing issues in areas of our app that utilize this function when running at higher loads.
Accessing Task.Result will block the current thread until the Task is complete, so it is not asynchronous.
As for deadlocks, this shouldn't happen, as Task.Run uses another thread for GetRequestAsync, which is not being blocked by the call to Result.
The reason that will not cause a deadlock is because Task.Run will push the delegate to be executed in a threadpool thread. Threadpool threads has no SynchronizationContext therefore no deadlock happens as there is no sync context to lock on between the async method GetRequestAsync and the caller. Same as you could have called .Result directly on the actual async method as well within Task.Run() block and that would not have caused a deadlock either.
Very inefficient though as you freeze 1 thread ie. 1 Core in the CPU do nothing but wait for the async method and I/O calls within it to complete. That s probably why you see a freeze in high load scenarios.
If you have a sync/async deadlock issue due to capturing sync context and blocking on async call, the deadlock will happen irrespective of load on a single call..
This won't cause a deadlock. But it's surely a resources wasting as one of the threads may be blocked.
The deadlock though may be possible if GetRequest looked like this:
protected T GetRequest<T>(string requestUri)
{
var task = GetRequestAsync<T>(requestUri);
return task.Result;
// or
// return GetRequestAsync<T>(requestUri).Result;
}
In example above you can see that I call GetRequestAsync within the current thread. Let's give the thread a number 0. Consider this line from the GetRequestAsync - await client.GetAsync(uri). .GetAsync is executed by a thread 1. After .GetAsync is done, default task scheduler is trying to return execution flow to the thread that executed the line - to the thread 0. But the thread that executed the line (0) is blocked right now as after we executed GetRequestAsync(), we are blocking it (thread 0) with task.Result. Hence our thread 0 remains blocked as it cannot proceed with execution of GetRequestAsync after await client.GetAsync(uri) is done nor it can give us the Result.
It's a pretty common mistake and I suppose you meant this one when asked about the deadlock. Your code is not causing it because you are executing GetRequestAsync from within another thread.

Should I add the async modifier if I return a Task in an expensive method?

The C# compiler already warns us if we have a method that has the async modifier but does not use the await operator.
According to this answer there's no point adding an await to the end of an async method (and in that case, just remove the async modifier).
But what if the method has an expensive synchronous operation it needs to perform before calling a subsequent true async method?
For example, if I'm using HttpClient:
private readonly HttpClient client = ...
public Task<HttpResponseMessage> CallMyWebServiceMethod() {
HttpRequestMessage request = this.SomeExpensiveButSynchronousMethod();
return this.client.SendAsync( request );
}
This code would block the caller (due to SomeExpensiveButSynchronousMethod).
However, if I change the code to this:
public async Task<HttpResponseMessage> CallMyWebServiceMethod() {
HttpRequestMessage request = this.SomeExpensiveButSynchronousMethod();
return await this.client.SendAsync( request );
}
and I call it like so:
HttpResponse response = await myWrapper.CallMyWebServiceMethod();
...I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod in the background thread, resuming whatever the parent code wants, making the entire call non-blocking in the process, before resuming after the Task completes and returns the HttpResponse.
...if that's the case then it seems contradictory.
If I'm wrong, and the call is blocking until it gets to SendAsync then how can I execute SomeExpensiveButSynchronousMethod on the same background thread as the HttpClient uses for its request?
According to this answer there's no point adding an await to the end of an async method (and in that case, just remove the async modifier).
That's an oversimplification. See my blog post on eliding async and await.
But what if the method has an expensive synchronous operation it needs to perform before calling a subsequent true async method?
This is a rare case, but the appropriate solution IMO is to execute the synchronous operation synchronously (i.e., not wrapped in a Task.Run) and be sure to document its behavior.
I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod in the background thread, resuming whatever the parent code wants, making the entire call non-blocking in the process, before resuming after the Task completes and returns the HttpResponse.
That is not at all what happens. You may find my async intro helpful. Quote:
The beginning of an async method is executed just like any other method. That is, it runs synchronously until it hits an “await” (or throws an exception).
In actuality, both of your examples synchronously block the caller while executing SomeExpensiveButSynchronousMethod.
If I'm wrong, and the call is blocking until it gets to SendAsync then how can I execute SomeExpensiveButSynchronousMethod on the same background thread as the HttpClient uses for its request?
HttpClient doesn't use a background thread for its request, so this part of the question doesn't make sense. For more information on how asynchronous I/O works, see my blog post There Is No Thread.
To answer the actual question:
Should I add the async modifier if I return a Task in an expensive method?
Yes. But the reason you should do so is not to "make it asynchronous"; it's so that any exceptions from SomeExpensiveButSynchronousMethod are captured and placed on the returned Task, which is the expected semantic for methods that follow the Task-based Asynchronous Pattern (TAP).
I understand the TPL would spin up a background thread immediately and then run CallMyWebServiceMethod
No, that's not what happens. The first synchronous part of an async method executes synchronously. If you want make sure it does not block the current thread, you should use Task.Run().
Your expensive method is going to block the caller either way. async doesn't magically create threads for you, that's what Task does (sometimes). So, if you add async and await the SendAsync, you're just adding state-machine overhead needlessly.
see also http://blog.stephencleary.com/2016/12/eliding-async-await.html

Is there any benefit in using await with an async method without intermediate work?

MSDN uses the below example:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
So the GetStringAsync method will basicallly promise to return a Task of type string at some point in the future, but by the time DoIndependentWork is called, getString hasn't been awaited yet so it can continue to do other work until this happens.
But the documentation then says
If AccessTheWebAsync doesn't have any work that it can do between
calling GetStringAsync and awaiting its completion, you can simplify
your code by calling and awaiting in the following single statement.
string urlContents = await client.GetStringAsync();
Is there any benefit to doing this at all if you're just going to await something straight away? Or is it just so you're preparing in advance to use asynchrony as your applications develops?
The main advantage is that await <some-operation-that-does-I/O> doesn't tie up a thread in a wait, improving resource utilization. A thread will only be commissioned when the I/O completes. You can have many more outstanding I/O requests on a system than you can have waiting threads. Stephen Cleary has an article on this that explains it more eloquently than I can.
The designer of an awaitable async method, thought that chances are high that somewhere during execution of the method he would have to wait for something to complete.
Instead of a busy wait, he gives you the possibility to do "something else" until you either need the result of the method or have nothing to do anymore.
It might be that you have no "something else" to do but your caller might or his caller. Even if no one has something else to do, using the async give the operator the opportunity to start something else, for instance minimize the window. We call this "keep the UI responsive".
So the answer is: yes, even if you have nothing to do and just await anyAsyncFunction(), it is meaningful to be an async function yourself whenever you call any other async function.

async/await. Where is continuation of awaitable part of method performed?

I am really curious how async/await enables your program not to be halted.
I really like the way how Stephen Cleary explains async/await: "I like to think of "await" as an "asynchronous wait". That is to say, the async method pauses until the awaitable is complete(so it waits), but the actual thread is not blocked (so it's asynchornous)."
I've read that async method works synchronously till compilator meets await keywords. Well. If compilator cannot figure out awaitable, then compilator queues the awaitable and yield control to the method that called method AccessTheWebAsync. OK.
Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn't depend on the result from AccessTheWebAsync before awaiting that result, or the caller might await immediately. The event handler is waiting for AccessTheWebAsync, and AccessTheWebAsync is waiting for GetStringAsync. Let's see an msdn example:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
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;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
Another article from msdn blog says that async/await does not create new thread or use other threads from thread pool. OK.
My questions:
Where does async/await execute awaitable code(in our example downloading a web site) cause control yields to the next row of code of our program and program just asks result of Task<string> getStringTask? We know that no new threads, no thread pool are not used.
Am I right in my silly assumption that CLR just switches the current executable code and awaitable part of the method between each other in scope of one thread? But changing the order of addends does not change the sum and UI might be blocked for some unnoticeable time.
Where does async/await execute awaitable code(in our example downloading a web site) cause control yields to the next row of code of our program and program just asks result of Task getStringTask? We know that no new threads, no thread pool are not used.
If the operation is truly asynchronous, then there's no code to "execute". You can think of it as all being handled via callbacks; the HTTP request is sent (synchronously) and then the HttpClient registers a callback that will complete the Task<string>. When the download completes, the callback is invoked, completing the task. It's a bit more complex than this, but that's the general idea.
I have a blog post that goes into more detail on how asynchronous operations can be threadless.
Am I right in my silly assumption that CLR just switches the current executable code and awaitable part of the method between each other in scope of one thread?
That's a partially true mental model, but it's incomplete. For one thing, when an async method resumes, its (former) call stack is not resumed along with it. So async/await are very different than fibers or co-routines, even though they can be used to accomplish similar things.
Instead of thinking of await as "switch to other code", think of it as "return an incomplete task". If the calling method also calls await, then it also returns an incomplete task, etc. Eventually, you'll either return an incomplete task to a framework (e.g., ASP.NET MVC/WebAPI/SignalR, or a unit test runner); or you'll have an async void method (e.g., UI event handler).
While the operation is in progress, you end up with a "stack" of task objects. Not a real stack, just a dependency tree. Each async method is represented by a task instance, and they're all waiting for that asynchronous operation to complete.
Where is continuation of awaitable part of method performed?
When awaiting a task, await will - by default - resume its async method on a captured context. This context is SynchronizationContext.Current unless it is null, in which case it is TaskScheduler.Current. In practice, this means that an async method running on a UI thread will resume on that UI thread; an async method handling an ASP.NET request will resume handling that same ASP.NET request (possibly on a different thread); and in most other cases the async method will resume on a thread pool thread.
In the example code for your question, GetStringAsync will return an incomplete task. When the download completes, that task will complete. So, when AccessTheWebAsync calls await on that download task, (assuming the download hasn't already finished) it will capture its current context and then return an incomplete task from AccessTheWebAsync.
When the download task completes, the continuation of AccessTheWebAsync will be scheduled to that context (UI thread, ASP.NET request, thread pool, ...), and it will extract the Length of the result while executing in that context. When the AccessTheWebAsync method returns, it sets the result of the task previously returned from AccessTheWebAsync. This in turn will resume the next method, etc.
In general the continuation (the part of your method after await) can run anywhere. In practice it tends to run on the UI thread (e.g. in a Windows application) or on the thread pool (e.g. in an ASP .NET server). It can also run synchronously on the caller thread in some cases ... really it depends on what kind of API you're calling and what synchronization context is being used.
The blog article you linked does not say that continuations are not run on thread pool threads, it merely says that marking a method as async does not magically cause invocations of the method to run on a separate thread or on the thread pool.
That is, they're just trying to tell you that if you have a method void Foo() { Console.WriteLine(); }, changing that to async Task Foo() { Console.WriteLine(); } doesn't suddenly cause an invocation of Foo(); to behave any differently at all – it'll still be executed synchronously.
If by "awaitable code" you mean the actual asynchronous operation, then you need to realize that it "executes" outside of the CPU so there's no thread needed and no code to run.
For example when you download a web page, most of the operation happens when your server sends and receives data from the web server. There's no code to execute while this happens. That's the reason you can "take over" the thread and do other stuff (other CPU operations) before awaiting the Task to get the actual result.
So to your questions:
It "executes" outside of the CPU (so it's not really executed). That could mean the network driver, a remote server, etc. (mostly I/O).
No. Truly asynchronous operations don't need to be executed by the CLR. They are only started and completed in the future.
A simple example is Task.Delay which creates a task that completes after an interval:
var delay = Task.Delay(TimeSpan.FromSeconds(30));
// do stuff
await delay;
Task.Delay internally creates and sets a System.Threading.Timer that will execute a callback after the interval and complete the task. System.Threading.Timer doesn't need a thread, it uses the system clock. So you have "awaitable code" that "executes" for 30 seconds but nothing actually happens in that time. The operation started and will complete 30 seconds in the future.

c# async runs single threaded?

I was reading http://msdn.microsoft.com/en-US/library/vstudio/hh191443.aspx.
Example code:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
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;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
The page also says:
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
Does this "no additional thread is created" applies within scope of the method marked as async?
I would imagine in order for both GetStringAsync and AccessTheWebAsync to be running at the same time (otherwise GetStringAsync will never finish as AccessTheWebAsync has control now), eventually GetStringAsync has to run on a different thread from AccessTheWebAsync's thread.
To me, writing async method is only useful at not adding more thread when the method it awaits is also async (which already use extra thread to do its own thing in parallel)
Is my understanding correct?
This is the key to the power of async. GetStringAsync and other naturally-asynchronous operations do not require a thread. GetStringAsync just sends out the HTTP request and registers a callback to run when the server replies. There's no need for a thread just to wait for the server to respond.
In reality, the thread pool is used just a tiny bit. In the example above, the callback registered by GetStringAsync will execute on a thread pool thread, but all it does is notify AccessTheWebAsync that it can continue executing.
I have an async intro blog post you may find helpful.
I would imagine in order for both GetStringAsync and AccessTheWebAsync to be running at the same time ...
They don't run at the same time (at least not in the way you're thinking). Now, if HttpClient.GetStringAsync itself
started work on a different thread, then that code could be running at the same time, -or-
Had an await (with ConfigureAwait(false)), then the remainder of the work in that method would be scheduled on to the Thread pool thread (and so that code could be running at the same time.
The point is that declaring a method as async and/or using await, doesn't cause the method that that you are authoring to be run on a separate thread (you would have to do that explicitly).
Note:
Without having the code (or documentation) of another asynchronous method, you don't really know how much of it is run synchronously. It doesn't really start being asynchronous until that method does an await or explicitly starts work on another thread (usually by starting a new Task)
There is a thread that is taken from the thread pool for the operation if that is necessary. In case of a console (not discussing the UI thread or IO threads) the current thread goes in the console and another thread is taken for the execution, and this new thread is the one that executes the remaining of the operation.
What the author is saying here, is that simply using the async and await keywords somewhere does not cause the current method to run on a different thread. Let's investigate what happens in the code provided.
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
Everything up to this point has executed in a single thread. At this point, the client.GetStringAsync call could spin off a new thread (although this is not guarenteed for any async method). It should be noted though that the GetStringAsync method essentially starts up on this current thread (such as actually making the call), but reading the response will execute in a different thread once it has returned. This is represented by it returning a Task object. The Task may represent an already completed bit of work, a currently executing secondary thread, or a unit of work that is simply scheduled to execute later.
DoIndependentWork();
This now executes on our primary thread, after the call has been queued (or possibly sent). Thus, this could be occuring while waiting for the request to be returned. Note that we are still on our primary thread.
string urlContents = await getStringTask;
At this point, our thread returns. .NET will create a continuation function containing the remainder of the method (return urlContents.Length;) which will automatically be called for us once the getStringTask completes on it's own thread. At that point, a new thread will pick up the continuation.
Through all of this, the entirety of what we wrote in our async method, up to the await keyword, ran in a single thread. Sure, we called another method that could happen to spawn another thread, but there was nothing that we did to create another thread just by using the async/await keywords. The continuation at the end can be called possibly by a different thread, but after our initial function has actually returned (Which is why our function returns a Task object, to represent work that may not have yet completed when any calls to this function returns).

Categories

Resources