Best practice to call ConfigureAwait for all server-side code - c#

When you have server-side code (i.e. some ApiController) and your functions are asynchronous - so they return Task<SomeObject> - is it considered best practice that any time you await functions that you call ConfigureAwait(false)?
I had read that it is more performant since it doesn't have to switch thread contexts back to the original thread context. However, with ASP.NET Web Api, if your request is coming in on one thread, and you await some function and call ConfigureAwait(false) that could potentially put you on a different thread when you are returning the final result of your ApiController function.
I've typed up an example of what I am talking about below:
public class CustomerController : ApiController
{
public async Task<Customer> Get(int id)
{
// you are on a particular thread here
var customer = await GetCustomerAsync(id).ConfigureAwait(false);
// now you are on a different thread! will that cause problems?
return customer;
}
}

Update: ASP.NET Core does not have a SynchronizationContext. If you are on ASP.NET Core, it does not matter whether you use ConfigureAwait(false) or not.
For ASP.NET "Full" or "Classic" or whatever, the rest of this answer still applies.
Original post (for non-Core ASP.NET):
This video by the ASP.NET team has the best information on using async on ASP.NET.
I had read that it is more performant since it doesn't have to switch thread contexts back to the original thread context.
This is true with UI applications, where there is only one UI thread that you have to "sync" back to.
In ASP.NET, the situation is a bit more complex. When an async method resumes execution, it grabs a thread from the ASP.NET thread pool. If you disable the context capture using ConfigureAwait(false), then the thread just continues executing the method directly. If you do not disable the context capture, then the thread will re-enter the request context and then continue to execute the method.
So ConfigureAwait(false) does not save you a thread jump in ASP.NET; it does save you the re-entering of the request context, but this is normally very fast. ConfigureAwait(false) could be useful if you're trying to do a small amount of parallel processing of a request, but really TPL is a better fit for most of those scenarios.
However, with ASP.NET Web Api, if your request is coming in on one thread, and you await some function and call ConfigureAwait(false) that could potentially put you on a different thread when you are returning the final result of your ApiController function.
Actually, just doing an await can do that. Once your async method hits an await, the method is blocked but the thread returns to the thread pool. When the method is ready to continue, any thread is snatched from the thread pool and used to resume the method.
The only difference ConfigureAwait makes in ASP.NET is whether that thread enters the request context when resuming the method.
I have more background information in my MSDN article on SynchronizationContext and my async intro blog post.

Brief answer to your question: No. You shouldn't call ConfigureAwait(false) at the application level like that.
TL;DR version of the long answer: If you are writing a library where you don't know your consumer and don't need a synchronization context (which you shouldn't in a library I believe), you should always use ConfigureAwait(false). Otherwise, the consumers of your library may face deadlocks by consuming your asynchronous methods in a blocking fashion. This depends on the situation.
Here is a bit more detailed explanation on the importance of ConfigureAwait method (a quote from my blog post):
When you are awaiting on a method with await keyword, compiler
generates bunch of code in behalf of you. One of the purposes of this
action is to handle synchronization with the UI (or main) thread. The key
component of this feature is the SynchronizationContext.Current which
gets the synchronization context for the current thread.
SynchronizationContext.Current is populated depending on the
environment you are in. The GetAwaiter method of Task looks up for
SynchronizationContext.Current. If current synchronization context is
not null, the continuation that gets passed to that awaiter will get
posted back to that synchronization context.
When consuming a method, which uses the new asynchronous language
features, in a blocking fashion, you will end up with a deadlock if
you have an available SynchronizationContext. When you are consuming
such methods in a blocking fashion (waiting on the Task with Wait
method or taking the result directly from the Result property of the
Task), you will block the main thread at the same time. When
eventually the Task completes inside that method in the threadpool, it
is going to invoke the continuation to post back to the main thread
because SynchronizationContext.Current is available and captured. But
there is a problem here: the UI thread is blocked and you have a
deadlock!
Also, here are two great articles for you which are exactly for your question:
The Perfect Recipe to Shoot Yourself in The Foot - Ending up with a Deadlock Using the C# 5.0 Asynchronous Language Features
Asynchronous .NET Client Libraries for Your HTTP API and Awareness of async/await's Bad Effects
Finally, there is a great short video from Lucian Wischik exactly on this topic: Async library methods should consider using Task.ConfigureAwait(false).

The biggest draw back I've found with using ConfigureAwait(false) is that the thread culture is reverted to the system default. If you've configured a culture e.g ...
<system.web>
<globalization culture="en-AU" uiCulture="en-AU" />
...
and you're hosting on a server whose culture is set to en-US, then you will find before ConfigureAwait(false) is called CultureInfo.CurrentCulture will return en-AU and after you will get en-US.
i.e.
// CultureInfo.CurrentCulture ~ {en-AU}
await xxxx.ConfigureAwait(false);
// CultureInfo.CurrentCulture ~ {en-US}
If your application is doing anything which requires culture specific formatting of data, then you'll need to be mindful of this when using ConfigureAwait(false).

I have some general thoughts about the implementation of Task:
Task is disposable yet we are not supposed to use using.
ConfigureAwait was introduced in 4.5. Task was introduced in 4.0.
.NET Threads always used to flow the context (see C# via CLR book) but in the default implementation of Task.ContinueWith they do not b/c it was realised context switch is expensive and it is turned off by default.
The problem is a library developer should not care whether its clients need context flow or not hence it should not decide whether flow the context or not.
[Added later] The fact that there is no authoritative answer and proper reference and we keep fighting on this means someone has not done their job right.
I have got a few posts on the subject but my take - in addition to Tugberk's nice answer - is that you should turn all APIs asynchronous and ideally flow the context . Since you are doing async, you can simply use continuations instead of waiting so no deadlock will be cause since no wait is done in the library and you keep the flowing so the context is preserved (such as HttpContext).
Problem is when a library exposes a synchronous API but uses another asynchronous API - hence you need to use Wait()/Result in your code.

Related

Is calling Task.Yield in Asp.Net Core ensuring continuation to run on the ThreadPool?

So Task.Yield will yield execution back to the caller immediately, essentially making whatever is bellow it in a continuation of the task returned by it (Task.Yield).
Assuming an Asp.Net Core application which does not have a SynchronizationContext, is there any functional difference from awaiting Task.Yield and passing that continuation to Task.Run?
Assuming an Asp.Net Core application which does not have a SynchronizationContext, is there any functional difference from awaiting Task.Yield and passing that continuation to Task.Run?
There's practically no difference. await Task.Yield will queue the continuation to the thread pool and return to the caller. await Task.Run will queue its delegate to the thread pool and return to the caller.
Personally, I prefer Task.Run because it has a very explicit intent and because it's unambiguous (i.e., in other scenarios such as GUI threads, await Task.Yield will not queue to the thread pool, while await Task.Run always does the same thing regardless of context).
As others have noted in the comments, there's no reason to actually do either one on ASP.NET Core, which is already running on thread pool threads and does not have a request context. It would add a little overhead to the request while providing no benefit at all.
They're difference, if you take the result as educational view point. Better explaination can be found here, here and... if you want to see how it compile to IL, take a shot here.
From real world project, as i saw the only purpose and benefit from Task.Yield is to force a task to run asynchronous. (decorate a method as async/await doesn't ensure that they will run asynchronously, especially with the new ValueTask).
So, forcing immediate return the execution to the caller, means that you doesn't care it's final result (for example: you call an API, but never care about the response).
Which according to me, in the asp.net core server side process, have a better approach, that's build a FireAndForget service and pass the task to it, let they run on a separate scope would be much safer.
That's cause the Task.Yield will capture the current context and goes on with it. So an exception would very likely to happen if you use resource that related to the current execution scope, HttpRequest is a particular case, which normally finish in less than a second(HttpContext already got disposed).

Async/await in Web.API 2 Controllers Action [duplicate]

Background
We are currently developing a web application, which relies on ASP .NET MVC 5, Angular.JS 1.4, Web API 2 and Entity Framework 6. For scalability reasons, the web application heavility relies on the async/await pattern. Our domain requires some cpu-intensive calculations, which can takes some seconds (<10s). In the past some team members used Task.Run, in order to speed up the calculations.Since starting an extra thread inside ASP .NET MVC or Web API controllers is considered a bad practise (the thread is not known by the IIS, so not considered on AppDomain Recycle => See Stephen Cleary's blog post), they used ConfigureAwait(false).
Example
public async Task CalculateAsync(double param1, double param2)
{
// CalculateSync is synchronous and cpu-intensive (<10s)
await Task.Run(() => this.CalculateSync(param1, param2))).ConfigureAwait(false);
}
Questions
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Does ConfigureAwait(false) really avoid the creation of an extra thread?
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Zero. None. In fact, you're hindering performance by spawning a new thread. Within the context of a web application, spawning a thread is not the same thing as running in the "background". This is due to the nature of a web request. When there's an incoming request, a thread is taken from the pool to service the request. Using async allows the thread to be returned before the end of the request, if and only if the thread is in a wait-state, i.e. idle. Spawning a thread to do work on, effectively idles the primary thread, allowing it to be returned to the pool, but you've still got an active thread. Returning the original thread to the pool does nothing at that point. Then, when the new thread finishes its work, you've got to request a main thread back from the pool, and finally return the response. The response cannot be returned until all work has completed, so whether you use 1 thread or a hundred, async or sync, the response cannot be returned until everything finishes. Therefore, using additional threads does nothing but add overhead.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
No, or more appropriately, it's not about that. ConfigureAwait is just an optimization hint, and only determines whether the original context is maintained between thread jumps. Long and short, it has nothing to do with the creation of a thread, and at least in the context of an ASP.NET application, has negligible performance impact either way.
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
No. And it doesn't matter whether it's CPU bound or not.
Task.Run offloads work to a ThreadPool thread. The web api request already uses a ThreadPool thread so you're just limiting scalability by offloading to another thread with no reason.
This is useful in UI apps, where the UI thread is a special single thread.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
It doesn't affect thread creating in one way or another. All it does is configures whether to resume on the captured SynchronizationContext or not.
Is there any performance benefit in using Task.Run in an async Web API Controller for cpu-bound operations?
Think about what really happens - Task.Run() creates a Task on the thread pool, and your await operator will free the thread (I'm assuming all methods down the stack are also awaiting). Now your thread is back to the pool, and it might pick up that same Task! In this scenario, there is obviously no performance gain. There is performance hit, actually. But if the thread picks up another Task (that's probably what will happen), another thread would have to pick up CalculateSync() Task and continue from where the former stopped. It would have made more sense to let the original thread execute CalculateSync() in the first place, no Tasks involved, and let the other thread have the other queued Tasks.
Does ConfigureAwait(false) really avoid the creation of an extra thread?
Not at all. It merely points out that the continuation shouldn't be executed on the caller's context.
There is one more thing that you need to consider. As you told your your api is doing CPU intensive task then async/await help to run the process in another thread and free your app pool for another request. Means your web api can handle more number of request per second if you use async/await correctly.
In your case look like this.CalculateSync(param1, param2) is non-async method so to call this asynchronously you have to use Task.Run.
I'll recommend to remove .ConfigureAwait(false) as this will actually decrease your performance.

What is the best practice for asynchronous programming in ASP.NET MVC?

According to this article ASP.NET requires using the same SynchronizationContext for asynchronous operations in the controller, otherwise it blocks the running thread. As a conclusion author mentioned that we should use both the methods as the best practice to prevent threads deadlocks:
In your “library” async methods, use ConfigureAwait(false) wherever possible.
Don’t block on Tasks; use async all the way down.
Note: It is best to apply both best practices. Either one will prevent
the deadlock, but both must be applied to achieve maximum performance and responsiveness.
But what purpose led Microsoft to use the same SynchronizationContext? May be using of the ConfigureAwait(false), which disables the same sync context restriction, might lead to e.g. unpredictable behavior or performance issues. Thus, is it really good practice to use the ConfigureAwait(false) wherever is possible?
ASP.NET requires using the same SynchronizationContext for
asynchronous operations in the controller, otherwise it blocks the
running thread.
I'm not really sure what that statement means. ASP.NET doesn't require "the same" synchronization context. In order for you to be inside your HttpContext, you need that SynchronizationContext.
But what purpose led Microsoft to use the same SynchronizationContext?
I suggest you read It's All About SynchronizationContext to get the bigger picture about sync contexts. Basically, it's a mechanism which allows you to post continuations on a particular thread. It can be used, for example, to marshal work back onto the UI message loop thread inside UI applications.
May be using of the ConfigureAwait(false), which disables the same
sync context restriction, might lead to e.g. unpredictable behavior or
performance issues
On the contrary. Marshaling work back onto the sync context does have (very minimal) overhead, as the request needs to be posted (using the abstract SynchronizationContext.Post) back onto the desired thread and context. By using ConfigureAwait(false), you're saving that time and simply continuing execution on which ever thread was allocated.
Thus, is it really good practice to use the ConfigureAwait(false)
wherever is possible?
The primary reason to do that is to avoid deadlocks. When someone calling Task.Result or Task.Wait instead of asynchronously waiting using await, you get the classic deadlock scenario where the sync context is attempting to post the continuation back onto the thread, but it is currently blocked because Result and Wait are blocking calls. The other reason is the minor performance overhead you get.
Edit:
Why doesn't Microsoft encapsulate this method inside the Task class?
It looks like the ConfigureAwait(false) has just only the pluses. Is
there any minuses?
Let's image the following scenario: You execute a method which returns a Task and is awaited using await, and right after that you update some UI element. Now, what would be more natural to you? Would you prefer to implicitly return to the same "environment" you were before (the UI thread), or would you prefer that you had to explicitly specify that you want to return to that same environment?
I think that the former "feels" more natural to the user.
Example:
public Task FetchAndReturnAsync(string url)
{
var httpClient = new HttpClient();
return httpClient.GetAsync(url);
}
You call it like this:
var awesomeUiResult = await FetchAndReturnAsync("http://www.google.com");
textBox.Text = awesomeUiResult;
What do you think should happen? Is it more natural for you to be able to update the text box after the await, or for it to fail because you're now not inside your original context?
ASP.NET requires using the same SynchronizationContext for asynchronous operations in the controller, otherwise it blocks the running thread.
Sort of, but not quite. ASP.NET creates a SynchronizationContext for each incoming request, and this context is not tied to a specific thread at all. However, only one thread at a time can enter the context, so if a second thread attempts to enter it while one is already in it, then it will block that thread.
what purpose led Microsoft to use the same SynchronizationContext?
The SynchronizationContext for ASP.NET manages per-request data such as HttpContext.Current, culture, and user identity.
is it really good practice to use the ConfigureAwait(false) wherever is possible?
As a general rule, yes, especially for generic libraries. On ASP.NET, ConfigureAwait(false) doesn't gain you much - in some cases, a minor performance increase. It can be used to avoid the deadlock I mention in my article, but it's far better (especially on ASP.NET) to use async all the way.

Is the use of [ThreadStatic] at odds with asynchronous code?

We have a fairly large existing code base for various webservices built on top of ASP.NET and that code makes heavy use of accessing HttpContext.Current.User (wrapped as Client.User) which I'm fairly sure internally uses [ThreadStatic] to give you that ambient scoping.
I'm currently looking into if it's possible that we start to use more asynchronous code in the form of async/await but I'm having a hard time finding how the use of [ThreadStatic] fits into this. Removing the reliance on [ThreadStatic] isn't really possible due to its heavy use.
It's my understanding that when an await is hit, the execution of the code stops there, the call immediately returns and that a continuation is set up to continue the execution when the asynchronous code returns. Meanwhile, the original thread is free to be used for something else, for example to handle another request. So far my understanding of it.
What I can't really find a definitive answer to is whether or not HttpContext.Current.User is guaranteed to be the same before and after the await.
So basically:
HttpContext.Current.User = new MyPrincipal();
var user = HttpContext.Current.User;
await Task.Delay(30000);
// Meanwhile, while we wait for that lots of other requests are being handled,
// possibly by this thread.
Debug.Assert(object.ReferenceEquals(HttpContext.Current.User, user));
Is that Debug.Assert guaranteed to succeed?
If another request was handled by the same thread as the Task.Delay was pending, that request will have set a different HttpContext.Current.User, so is that previous state somehow stored and restored when the continuation is called?
What I can imagine happening is that behind the scenes the [ThreadStatic] state is kept as some sort of dictionary on the thread itself and that when a thread returns to the thread pool after returning on that await that dictionary is kept safe somewhere and set back onto the thread when it executes the continuation (or on a thread, I'm not sure if it's necessarily even the same thread that handles the continuation), probably with an encouraging pat on the butt and a "go get 'em boy!", but that last part might just be my imagination.
Is that somewhat accurate?
UPDATE: I've tried to put together a small test that attempts this. So far it seems to work and the assertion hasn't failed for any out of hundreds of requests. Can anyone verify if the test makes sense?
https://gist.github.com/anonymous/72d0d6f5ac04babab7b6
async/await are thread-agnostic, meaning that they have a convention that can work within multiple different threading systems.
In general ThreadStatic will not work correctly in async/await, except for trivial cases such as UI contexts where await will resume on the UI thread. For ASP.NET, ThreadStatic is not compatible with async.
However, HttpContext.Current is a special case. ASP.NET defines a "request context" (represented by an AspNetSynchronizationContext instance assigned to SynchronizationContext.Current). By default, awaiting a task will capture this synchronization context and use it to resume the method. When the method resumes, it may be on a different thread, but it will have the same request context (including HttpContext.Current as well as other things such as culture and security).
So, HttpContext.Current is preserved, but any of your own ThreadStatic values are not.
I describe how await works with SynchronizationContext in my async intro. If you want more details, check out my SynchronizationContext MSDN article (particularly the last section on the async CTP).
ThreadStatic is not at odds per se with asynchronous code at all. It is often used in that context to improve performance, by giving each thread its own copy of a specific object, eliminating contention.
Of course, it has to be used carefully. And if you have a scenario where you require the same object instance to be used regardless of which thread the code executes in, then ThreadStatic either won't work, or it will require careful handling of the threads to ensure that each flow of execution comes back to the thread where it belongs.
In some async/await scenarios, you are guaranteed that the continuation happens on the same thread as the original await. For example, when you await from within a GUI thread in a Forms or WPF program. But this is not guaranteed by the async/await features in general.
Ultimately, while you can use ThreadStatic with async/await, you still need to make sure you're using it in the way it's meant: to tie a specific value or object to a specific thread. This is great for general-purpose objects where any given flow of execution that might be continued doesn't care which object it actually uses. Or where you're sure the flow of execution remains in a given thread.
But otherwise, no. You don't want to be using ThreadStatic in scenarios where at the same time you need the flow of execution to always use the same object, but you cannot guarantee that the flow of execution will remain on the same thread. (Sorry if that last statement seems obvious…I just want to make sure it's clear).
Assuming the await was called from a async-friendly call stack (async controller / handler) then, yes, the assert is guaranteed to succeed.
The ASP.NET SynchronizationContext will handle making HttpContext available on return threads (unless you use ConfigureAwait(false)). However this does not apply to thread data in general, so prefer HttpContext.Items if you have that type of "request global" state.

ConfigureAwait when not awaiting

I have an async method I am using to offload a few seconds' worth of fire-and-forget work so as not to slow down my page load. This work needs a bit of general setup and tidy-up; I want the (fast) setup to throw synchronously if it throws, but I don't want to force the tidy-up to run in the ASP context so I am using ConfigureAwait on the bit I am awaiting:
public Task FireAndForget()
{
DoSetup();
return FireAndForgetAfterSetup();
}
private async Task FireAndForgetAfterSetup()
{
await AFewSecondsWorthOfWork().ConfigureAwait(false);
DoTidyUp();
}
protected void btn_Click(object sender, EventArgs e)
{
FireAndForget();
}
This seems odd, because
FireAndForgetAfterSetup shouldn't really care whether or not it is being called from an ASP context, so why should it have to be the one calling ConfigureAwait?
If I change my mind and decide that btn_Click should wait for FireAndForget to complete, has it already thrown away the ASP context(?)
Can someone explain to me if I'm misunderstanding?
The ASP.NET synchronization context doesn't allow fire-and-forget work items to be kicked off from within a request. The runtime actively monitors such things and will try to generate an exception since these code patterns lead to null refs, deadlocks, AVs, and other nastiness.
If you absolutely need to kick off fire-and-forget work in ASP.NET, consider using WebBackgrounder. It integrates with the ASP.NET extensibility points that are designed to allow for this. So it won't block the active request, but keep in mind Stephen's caveat: it's not ever guaranteed to be executed at all. If you require guaranteed execution, consider a reliability mechanism like Service Bus.
If your scenario is how to execute some (relatively) long-running task during load, ASP.NET allows this scenario through the Page.RegisterAsyncTask method. Scott Hansleman describes how to use it in The Magic of using Asynchronous Methods in ASP.NET 4.5 plus an important gotcha
Essentially, you create an asynchronous method that returns Task and call:
RegisterAsyncTask(new PageAsyncTask(MyAsyncMethod));
then call Page.ExecuteRegisteredAsyncTasks to start executing all registered tasks.
Scott Hanselman does a good job (of course) of describing why using an event handler, Task or background thread is a bad idea.
This is also described in "What Not to do in ASP.NET, What to do instead" in the "Asynchronous Page Events" section
I'm not sure why he didn't post it, but my exact two questions are answered in this blog post by Stephen Cleary:
The important thing to note with this example is that each "level" of async method calls has its own context. DownloadFileButton_Click started in the UI context, and called DownloadFileAsync. DownloadFileAsync also started in the UI context, but then stepped out of its context by calling ConfigureAwait(false). The rest of DownloadFileAsync runs in the thread pool context. However, when DownloadFileAsync completes and DownloadFileButton_Click resumes, it does resume in the UI context.
A good rule of thumb is to use ConfigureAwait(false) unless you know you do need the context.
In answer to my first bullet point, yes, it's OK (encouraged!) to use ConfigureAwait(false) in library methods that know they won't use the context, because...
... in answer to my second bullet point, even if the library async method has thrown away the UI context, the calling method still has its own copy. Thus the calling method could await the library method and resume in the UI context... but it's going to deadlock when that happens.

Categories