It is known that synchronous waiting on an async method leads to deadlocks
(see, for example Don't Block on Async Code)
I have the following code in an event handler for a button-click in a Windows Forms application (i.e. the code is invoked with a UI SynchronizationContext installed).
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
Task<HttpResponseMessage> t = client.SendAsync(request);
t.Wait();
var response = t.Result;
I fully expected the code to deadlock on clicking the button. However, what I actually see is synchronous waiting - the dialog becomes unresponsive for a while, and then accepts events as usual.
I consistently see deadlocks when I try to synchronously wait on client async methods. However, synchronously waiting on library async methods like SendAsync or ReadAsByteArrayAsync seems not to deadlock. Can someone explain this behaviour?
Don't implementations of async methods in .NET libraries use await statements internally, so that the continuations have to be marshalled back to the original SynchronizationContext?
Note:
If I define a client method, say
public async Task<byte[]> wrapperMethod()
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
var response = await client.SendAsync(request);
return await response.Content.ReadAsByteArrayAsync();
}
and then say byte[] byteArray = wrapperMethod().Result; in the button click handler, I do obtain a deadlock.
Don't implementations of async methods in .NET libraries use await statements internally?
Generally, no. I have yet to see a single implementation in the .NET framework that uses async-await internally. It does use tasks and continuations but not the compiler magic the async and await keywords bring.
Using async-await is simple as the code looks synchronous but actually runs asynchronously. But that simplicity has a very small price in performance.
For most consumers this prices is worth paying, but the framework itself tries to be as performant as possible.
However, synchronously waiting on library async methods like SendAsync or ReadAsByteArrayAsync seems not to deadlock.
The deadlock is a result of the default behaviour of await. When you await an uncompleted task the SynchronizationContext is captured and when it's completed the continuation is resumed on that SynchronizationContext (if it exists). When there's no async, await, captured SynchronizationContext, etc. this kind of deadlock can't happen.
HttpClient.SendAsync specifically uses TaskCompletionSource to return a task without marking the method as async. You can see that in the implementation on github here.
Most task-returning methods added to existing classes for async-await simply build a task using the already existing asynchronous API (i.e. BeginXXX/EndXXX). For example this is TcpClient.ConnectAsync:
public Task ConnectAsync(IPAddress address, int port)
{
return Task.Factory.FromAsync(BeginConnect, EndConnect, address, port, null);
}
When you do use async-await though you avoid the deadlock by using ConfigureAwait(false) when you don't need to capture the SynchronizationContext. It's recommended that libraries should alway use it unless the context is needed (e.g. a UI library).
You won't cause a deadlock by blocking on most out-of-the box Task-returning .NET calls because they wouldn't internally touch the SynchronizationContext that the Task was started on unless absolutely necessary (two reasons: performance and avoiding deadlocks).
What this means is that even if standard .NET calls did use async/await under the covers (i3arnon said they don't - I won't argue as I simply don't know), they would, beyond any doubt, use ConfigureAwait(false) unless capturing the context is definitely required.
But that's the .NET framework. As for your own code, you will observe a deadlock if you call wrapperMethod().Wait() (or Result) in your client (provided that you're running with a non-null SynchronizationContext.Current - if you're using Windows Forms, this will definitely be the case). Why? Because you're flaunting async/await best practices by not using ConfigureAwait(false) on your awaitables inside async methods that do not interact with the UI, causing the state machine to generate continuations that unnecessarily execute on the original SynchronizationContext.
Related
I have three tier .net web api application. each tier is implementing a async method. Each call is async and and we are using await at each step. My question is when you await at every step, doesn't it make the application synchronous & defeats the purpose ? What value async await really provides? Does it automatically uses multiple CPU cores?
Controller:
public async Task<IHttpActionResult> Get()
{
return Ok(await _service.Create());
}
middle tier:
public async Task<MyObject> Create()
{
return await _repository.CreateAsync(new MyDataObject());
}
DB
public async Task<T> CreateAsync(T data)
{
var o = _dbSet.Add(data);
await _dbContext.SaveChangesAsync();
return 100;
}
In your example you're definitely doing asynchronous processing. What you're not doing is parallel processing. The .NET documentation doesn't always do a good job of differentiating between the two. I'll just cover asynchronous here.
The main idea behind async / await (which your examples do well) is to not have a thread sitting around doing nothing when it could be doing something useful.
Take your CreateAsync example:
public async Task<T> CreateAsync(T data)
{
var o = _dbSet.Add(data);
await _dbContext.SaveChangesAsync();
return 100;
}
The database changes won't happen any faster because of the await. So what's the benefit? For the sake of argument assume the following:
Your app has 5 users
Your app has 2 threads available (way low, but play along)
Each database save takes 3 seconds
Now assume User A and User B save a record at the same time. Each has their own thread (that's a fact, not an assumption). If you aren't using await then users A and B will hold both of your available threads for 3 seconds just waiting for the save to complete. No more threads are available, so users C, D and E will be blocked for that period.
When you use await, the threads are released because they're just... waiting. Now they can take care of users C, D, and E. When the save completes the threads will come back for users A and B and finish the CreateAsync method.
Bottom line, when async / await is done properly n threads can fulfill way more than n requests.
This is a simplified explanation, but I really wish I'd gotten a simple explanation way back when. I hope this helps.
What value async await really provides?
It allows your web server to process more requests at the same time; async/await allows the threads to do other work while the code waits for the db to do its work (db or cache, email service, external api call, etc.).
From Async Programming : Introduction to Async/Await on ASP.NET:
(...) let’s say the requests in the system depend on some external resource, like a database or Web API. When a request comes in, ASP.NET takes one of its thread pool threads and assigns it to that request. Because it’s written synchronously, the request handler will call that external resource synchronously. This blocks the request thread until the call to the external resource returns.
...
Asynchronous request handlers operate differently. When a request comes in, ASP.NET takes one of its thread pool threads and assigns it to that request. This time the request handler will call that external resource asynchronously. This returns the request thread to the thread pool until the call to the external resource returns.
When you await an async method in C#, it does not necessarily mean that the method is executed asynchronously. It simply means that the calling method will be suspended until the awaited task completes.
The async and await keywords in C# are used to simplify the process of writing asynchronous code. They allow you to write code that looks and reads like synchronous code, while still being asynchronous under the hood.
To understand how async and await work, it is important to know that an async method actually returns a Task or Task object, which represents the asynchronous operation. The await operator is used to suspend the execution of the calling method until the awaited Task completes.
However, just because a method is marked async does not necessarily mean that it will be executed asynchronously. The actual execution of the method depends on how the Task is implemented and whether it is running on a thread pool thread or not.
For example, if the Task is running on a ThreadPool thread, it will be executed asynchronously. On the other hand, if the Task is implemented using the Task.Run method, it will be executed synchronously on a separate ThreadPool thread.
In short, the async and await keywords in C# allow you to write asynchronous code that is easier to read and maintain, but they do not guarantee that the code will be executed asynchronously.
Each call is async and and we are using await at each step. My question is when you await at every step, doesn't it make the application synchronous & defeats the purpose?
First of all, synchronous and asynchronous is a property of a method or an execution flow, not a property of the application as a whole. In your case you await on every level and every step all asynchronous operations (Tasks) that you start, so the execution flow of each web request is asynchronous. It's still a single execution flow though. The code is executed in a sequential/serialized fashion. In the context of a single web request, no concurrency is happening.
The difference from a classic and familiar synchronous execution flow is that the flow is not forced to run on the same thread from start to finish. Different threads might be involved in the execution, but not more than one thread at the same time. A thread-switch might occur at each await point, and whether it will happen depends on various factors that might not be under your direct control. The most interesting aspect of an asynchronous flow is that, time-wise, large parts of the execution are usually not running on any thread. For example while the _dbContext.SaveChangesAsync() is doing its job, there is no thread in your process that is blocked waiting for this work to be done. This means that your web application can have a large number of concurrent executions flows (web requests), using only a small number of threads. Which eventually results in increased scalability for your application: you can serve more users with less hardware.
Relatively new developers who come to asynchronous programming directly using async/await may have this confusion. To understand and appreciate the value of what async/await brings to table, one has to go slightly back in time and review how asynchronous code was written then.
Before the keywords were introduced in C#, asynchronous programming was still possible. Traditionally (.NET Framework 2.0 later), there were two patterns:
Event-based Asynchronous Pattern (EAP), where you subscribed to an event:
o.ReadCompleted += (o, e) => { // asynchronously called after ReadAsync completion };
o.ReadAsync(buffer, count); // begin the async process
Task-based Asynchronous Pattern (TAP), which is Promise like interface where you can setup completions with then and catch.
o.ReadAsync(buffer, count)
.then( (result) => { // asynchronously called after ReadAsync completion } );
So, advantage of asynchronous programming on the server is that the calling thread is not blocked on the Read, which is now an asynchronous call as against a synchronous call. The thread can do some other tasks / or serve other requests.
When I/O bound Read eventually completes, the completion delegate will be called, possibly over a different thread. This way there are more threads available which makes the service more scalable. This is advantage of asynchronous programming.
However, the two patterns above have a disadvantage for the developer that the code becomes unreadable and inside-out because it is not written sequentially.
The async/await keywords just let us keep the same advantages of asynchronous programming, while making the code readable.
Now we just write:
var result = await o.ReadAsync(buffer, count);
// here comes code that we had to previously write inside the completion delegate
// but now its more readable, and much natural to handle exceptions
So although it looks sequential to developer it is still asynchronous. The compiler converts the async method into a state machine which behaves similar to code previously written, but hides away all the complex details from the developer. Similar to the completion delegate behavior, the code written after await could also be resumed on a different thread.
I am trying to understand something about async programming in general.
In C# it seems that everyone is now using async await syntatic sugar for async operations that are IO bound.
My question is: Does any operation that is IO bound like a file reading, http request etc that was sync until now can become asnync by writting a wrapper function that is async?
Or since the underlying "old" implementation if it is sync will not help at all?
will the thread that used to wait until now will be released or not?
Anyone?
Wrapping a method that is sync with an async method can have some benefits. The underlying method will still be synchronous, but you can offload that method to another thread, so the thread that used to wait can now continue it's execution. So in your example, if the UI thread calls the blocking method GetHTTPResource, you can achieve UI responsiveness by offloading that method to another thread using an asynchronous wrapper. I recommend you this blog post, which I think can give you a better understanding of what async over sync implies. (An this other covers sync over async).
With async over sync, there will still be a thread blocked. That is the reason why it makes little sense in case of a web application, using asynchronous wrappers for synchronous functions has no performance benefits. Quoting the aforementioned article (emphasis mine):
The ability to invoke a synchronous method asynchronously does nothing
for scalability, because you’re typically still consuming the same
amount of resources you would have if you’d invoked it synchronously
(in fact, you’re using a bit more, since there’s overhead incurred to
scheduling something ), you’re just using different resources to do
it, e.g. a thread from a thread pool instead of the specific thread
you were executing on. The scalability benefits touted for
asynchronous implementations are achieved by decreasing the amount of
resources you use, and that needs to be baked into the implementation
of an asynchronous method… it’s not something achieved by wrapping
around it.
For instante, in case of an ASP.NET application, fully async code allows threads to process new requests while other requests are waiting for I/O operations to complete, thus achieving higher scalability. On the other hand, if the code has underlying synchronous methods for I/O operations, there will be threads blocked that won't be able to do anything but wait until these operations complete. So async over sync usually has no benefit in case of web applications.
Yes, your sync function can become async, for example in HTTP Request you can change your Sync function
public static Task<HttpResponseMessage> GetRequest(string requestUri, Dictionary<string, string> requestHeaders)
{
return HttpRequestFactory.Get(requestUri, requestHeaders);
}
Calling function
var result = HttpClient.GetRequest(requestUri, _request, _requestHeaders)
you will change this into async like this
public static async Task<HttpResponseMessage> GetRequest(string requestUri, Dictionary<string, string> requestHeaders)
{
return await HttpRequestFactory.Get(requestUri, requestHeaders);
}
calling function to
var result = HttpClient.GetRequest(requestUri, _request, _requestHeaders).Result;
Hope so this will help to you..
I'm developing an MVC web application that allows me to manage my data asynchronously through a web service.
It is my understanding this allows the CPU threads that access the app pool for the server upon which this website is running to return to the app pool after making a request so that they can be used to service other requests without stalling the entire thread.
Assuming my understanding is correct (although it may be badly worded), I got to thinking about when I should await things. Consider the function below:
public async Task<ActionResult> Index()
{
List<User> users = new List<User>();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:41979");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/user/");
if (response.IsSuccessStatusCode)
{
users = await response.Content.ReadAsAsync<List<User>>();
}
}
return View(users);
}
All of my functions look similar except that they do different things with the data returned by the web service and I got to wondering, should I not await the return as well?
Something like:
return await View(users);
or
await return View(users);
I mean the website runs just fine so far except that I've had a bit of confusion to do with exactly what the web service should send back to the client website, but as I'm new to development involving a web service, I'm still wondering if I'm doing things properly and this has been eating at me for some time.
You can only await named or anonymous methods and lambda expressions which expose an asynchronous operation via Task, Task<T> or a custom awaiter. Since View by itself does nothing asynchronous, you can't await it.
What is actually the point of using await? Usually, you have some IO bound operations which is asynchronous by nature. By using async API's, you allow the thread to be non-blocked by returning to the thread-pool, making use of it to serve different requests. async does not change the nature of HTTP. It is still "request-response". When an async method yields control, it does not return a response to the client. It will only return once the action has completed.
View(object obj) returns a ViewResult, which in turn will transform your object into the desired output. ViewResult is not awaitable, as it doesn't expose any "promise" via an awaitable object. Thus, you can't asynchronously wait on it.
I got to thinking about when I should await things
It's better to always await the result from asynch calls.
If you don't await, you fire & forget, you don't receive response on your end in both success and error cases.
You "await" when you need to unwrap the async task as a value. Other wise you can return a task and have it run at a later time if needed. Also note that .Wait() is not the same as await. Wait() will block until the task has finished (side note I know). Also check your code, you have a syntax error in your method signature:
public async <Task>ActionResult> Index()
Should be
public async Task<ActionResult> Index()
I think it is a very good question and also very hard to answer it especially in the case of a web site.
I've had a bit of confusion to do with exactly what the web service should send back to the client website'
The most important thing to understand if you use async/await, then your action method code still serialized, I mean the next line will be executed only after the async operation finished. However there will be (at least) three threads:
To original web server worker thread in which the action method is
called. Originally the MVC infrastructure got this thread from the
pool, and dedicated this thread to serve the current request.
Optional thread(s) what are started by the async operation what can
be called with await.
A continuation thread (also a worker from the
pool) in which your action method is continuing after the await. Note
this thread will have the same context (HttpContext, user culture
etc) what was the original worker so it's transparent for you, but it will be an other thread freshly allocated from the pool.
For the first sight it has no sense: Why all those thread hocus-pocus in case if the operations in the action method are still serialized? I takes the same time... To understand this we must take a look to a desktop application say a WPF app.
To be short: There is a message loop and a dedicated thread which reads the UI (and other virtual) events from a queue and executes the event handlers in the context of this thread, like a button click event. In case you block this thread for 2 second the UI will be unresponsive for that time. So that's why we would like to do many things in async way in an other thread, and let the dedicated (UI) thread to fast return and process other messages from the queue. However this could be very inconvenient, because we sometime wanted to continue something after the async operation ended and we had the result. The C# feature async/await made this very convenient. This case the continuation thread is always the dedicated UI thread but in its (very) later round in its endless loop. To wrap it up:
In an event handler you can use async/await to still execute your operations in serialized, the continuation will be done always in the original dedicated UI thread but during the await this thread can loop, and process other messages.
Now back to the MVC action method: In this case your action method is the analogy of the event handler. Although it is still hard to understand the use of the thread complication: This case blocking the action method would not block anything (as it blocked the dedicated UI thread in WPF). Here are the facts:
Other clients (browsers) requests will be served by other threads. (so we are
not blocking anything by blocking this thread (*) keep reading
This request will not be served faster even if we use async/await because
the operations are serialized and we must wait (await) the result of
the async operation. (Do not confuse async/await with parallel processing)
So the use of async/await and the transparent thread tricks is not so obvious as it was in the case of the desktop application.
Still: Pool is not an endless resource. Releasing ASAP back to the pool (by await) the worker thread what was originally dedicated to serve the request, and let continue in an other thread after completion the async operation may lead better utilization of the thread pool and may lead better performance of the web server under extreme stress.
Why is it possible to do this in C#?
var task = Task.Run (...);
await task;
Isn't Task.Run() supposed to be used for CPU-bound code? Does it make sense to call awaitfor this?
I.e., after calling Task.Run I understand that the task is running in another thread of the thread pool. What's the purpose of calling await? Wouldn't make more sense just to call task.Wait()?
One last question, my first impression was that await is intended to be used exclusively with async methods. Is it common to use it for task returned by Task.Run()?
EDIT. It also makes me wonder, why do we have Task.Wait () and not a Task.Await(). I mean, why a method is used for Wait() and a keyworkd for await. Wouldn't be more consistent to use a method in both cases?
There would be no point at all in using Wait. There's no point in starting up a new thread to do work if you're just going to have another thread sitting there doing nothing waiting on it. The only sensible option of those two is to await it. Awaiting a task is entirely sensible, as it's allowing the original thread to continue execution.
It's sensible to await any type of Task (in the right context), regardless of where it comes from. There's nothing special about async methods being awaited. In fact in every single asynchronous program there needs to be asynchronous methods that aren't using the async keyword; if every await is awaiting an async method then you'll never have anywhere to start.
There are several good answers here, but from a more philosophical standpoint...
If you have lots of CPU-bound work to do, the best solution is usually the Task Parallel Library, i.e., Parallel or Parallel LINQ.
If you have I/O-bound work to do, the best solution is usually async and await code that is built around naturally-asynchronous implementations (e.g., Task.Factory.FromAsync).
Task.Run is a way to execute a single piece of CPU-bound code and treat it as asynchronous from the point of view of the calling thread. I.e., if you want to do CPU-bound work but not have it interfere with the UI.
The construct await Task.Run is a way to bridge the two worlds: have the UI thread queue up CPU-bound work and treat it asynchronously. This is IMO the best way to bridge asynchronous and parallel code as well, e.g., await Task.Run(() => Parallel.ForEach(...)).
why a method is used for Wait() and a keyword for await.
One reason that await is a keyword is because they wanted to enable pattern matching. Tasks are not the only "awaitables" out there. WinRT has its own notion of "asynchronous operations" which are awaitable, Rx observable sequences are awaitable, Task.Yield returns a non-Task awaitable, and this enables you to create your own awaitables if necessary (e.g., if you want to avoid Task allocations in high-performance socket applications).
Yes, it's common and recommended. await allows to wait for a task (or any awaitable) asynchronously. It's true that it's mostly used for naturally asynchronous operations (e.g. I/O), but it's also used for offloading work to be done on a different thread using Task.Run and waiting asynchronously for it to complete.
Using Wait not only blocks the calling thread and so defeats the purpose of using Task.Run in the first place, it could also potentially lead to deadlocks in a GUI environment with a single threaded synchronization context.
One last question, my first impression was that await is intended to be used exclusively with async methods
Whether a method is actually marked with the async modifier is an implementation detail and most "root" task returning methods in .Net aren't actually async ones (Task.Delay is a good example for that).
Wouldn't make more sense just to call task.Wait()?
No, if you call Wait you're involving two threads there, one of the worker threads from the ThreadPool is working for you (given the task is CPU bound), and also your calling thread will be blocked.
Why would you block the calling thread? The result will be too bad if the calling thread is a UI thread! Also if you call Task.Run immediately followed by Task.Wait you're making it worse, too. It is no better than calling the delegate synchronously. There is no point whatsoever in calling Wait immediately after starting a Task.
You should almost never use Wait, always prefer await and release the calling thread.
It is very common and useful for cases like (greatly simplified; production code would need exception handling, for instance):
async void OnButtonClicked()
{
//... Get information from UI controls ...
var results = await Task.Run(CpuBoundWorkThatShouldntBlockUI);
//... Update UI based on results from work run in the background ...
}
Regarding the comment of your later edit, 'await' is not a method call. It is a keyword (only allowed in a method that has been marked 'async', for clarity) that the compiler uses to decide how to implement the method. Under the hood, this involves rewriting the method procedure as a state machine that can be paused every time you use the 'await' keyword, then resumed when whatever is it awaiting calls back to indicate that it is done. This is a simplified description (exception propagation and other details complicate things), but the key point is that 'await' does a lot more than just calling a method on a Task.
In previous C# versions, the closest construct to this 'async/await' magic was the use of 'yield return' to implement IEnumerable<T>. For both enumerations and async methods, you want a way to pause and resume a method. The async/await keywords (and associated compiler support) start with this basic idea of a resumable method, then add in some powerful features like automatic propagation of exceptions, dispatching callbacks via a synchronization context (mostly useful to keep code on the UI thread) and automatic implementation of all the glue code to set up the continuation callback logic.
I have a library that exposes synchronous and asynchronous versions of a method, but under the hood, they both have to call an async method. I can't control that async method (it uses async/await and does not use ConfigureAwait(false)), nor can I replace it.
The code executes in the context of an ASP .NET request, so to avoid deadlocks, here's what I've done:
var capturedContext = SynchronizationContext.Current;
try
{
// Wipe the sync context, so that the bad library code won't find it
// That way, we avoid the deadlock
SynchronizationContext.SetSynchronizationContext(null);
// Call the async method and wait for the result
var task = MyMethodAsync();
task.Wait();
// Return the result
return task.Result;
}
finally
{
// Restore the sync context
SynchronizationContext.SetSynchronizationContext(capturedContext);
}
Does this produce the same effect as if MyMethodAsync had used ConfigureAwait(false) on all of its await's? Are there some other problems with this approach that I'm overlooking?
(MyMethodAsync is completely unaware that it's being run in an ASP .NET context, it doesn't do any calls to HttpContext.Current or anything like that. It just does some async SQL calls, and the writer didn't put ConfigureAwait(false) on any of them)
I have a library that exposes synchronous and asynchronous versions of a method, but under the hood, they both have to call an async method.
The library is wrong to expose a synchronous version. Just pretend the synchronous API doesn't exist.
so to avoid deadlocks
There shouldn't be any problems with deadlocks if you call an asynchronous method that uses async/await. If it doesn't use ConfigureAwait(false), then it's not as efficient as it could be, that's all. Deadlocks due to ConfigureAwait(false) only apply when you're trying to do sync-over-async (i.e., if you're calling the synchronous APIs from that library).
So, the easiest and simplest solution is to just ignore the synchronous APIs, which are incorrectly designed anyway:
return await MyMethodAsync();
Provided you wrap this technique in a suitably named static function, I think your suggest is significantly better than Task.Run, even if still the lesser of two evils.
Task.Run has a number of issues:
It is not clear why you are using it, you want to start a new task on a web server? This will be deleted by new developers fast if there are no comments. And then boom, difficult to diagnose production issues (deadlocks).
It starts on a new thread pool thread when it doesn't need to until it reaches its first await completed continuation.
It makes you block synchronously for the entire Task returning function, when from your description of the problem, the blocking is actually just part of the overall task. What is being encouraged here is longer blocking over async code, this is certainly not what you want.
If you use it multiple levels, you are multiplying the problem (with SetSynchronizationContext there's no harm in doing it more than once).
If it turns out that there was no blocking / deadlock where you thought there was, or it had been fixed, Task.Run now is introducing blocking over async, whereas SetSynchronizationContext will not cost you anything, in addition to the optimizations it makes by not resuming on the context constantly.
I also understand there is hesitance to make any recommendation given blocking on async code should be avoided at all costs, however you have made it clear you are aware of this and this is to fix a known case of this outside of your immediate control. I think the dogmatic attitude towards this topic is damaging to the .NET ecosystem.
Setting the SynchronizationContext to null seems hacky for me. Instead you can really delegate the work to threadpool. Use Task.Run..
var result = Task.Run(() => MyMethodAsync()).Result;
or
var result = Task.Run(async () => await MyMethodAsync()).Result;
This avoids the deadlock and eliminates the hacky code as well.