Can I rely on CallContext using Web API? - c#

Can CallContext be relied upon, through-out the whole request, when using asp.net Web API?
I have read the decade-old blog post and I'm not sure it still applies (as asked there).
Assuming Thread-Agility kicks in, if I set data in a global filter, is it safe to assume it will be there through-out the request?

You lose your CallContext if ASP.Net switches threads. In an asynchronous model, the asp.net task scheduler will take care of joining async calls back to a request thread with the same HttpContext, but not necessarily the same thread.
Example: A request starts and then you go off to asynchronously wait for some slow IO before returning - while you're waiting for that slow IO there's no reason for your request thread to be sitting around doing nothing so it may get used for another request.
ASP.Net is a big exercise in Thread Agility (google it), and there is also a great discussion about this here: CallContext vs ThreadStatic vs HttpContext

Related

C# async/await in backend service / webservice usefull?

Is async/await useful in a backend / webservice scenario?
Given the case there is only one thread for all requests / work. If this thread awaits a task it is not blocked but it also has no other work to do so it just idles. (It can't accept another request because the current execution is waiting for the task to resolve).
Given the case there is one thread per request / "work item". The Thread still idles because the other request is handled by another thread.
The only case I can imagine is doing two async operations at a the same time is like reading a file and sending an http request. But this sounds like a rare case. Is should read the file first and then post the content and not post something I didn't even read.
Given the case there is one thread per request / "work item". The Thread still idles because the other request is handled by another thread.
That's closer to reality but the server doesn't just keep adding threads ad infinitum - at some point it'll let requests queue if there's not a thread free to handle the request. And that's where freeing up a thread that's got no other work to usefully do at the moment starts winning.
It's hard to read your question without feeling that you misunderstand how webservers work and how async/await & threads work. To make it simple, just think of it like this: async/await is almost always good to use when you query an external resource (e.g. database, web service/API, system file, etc). If you follow this simple rule, you don't need to think too deeply about each situation.
However, when you read & learn more on these subjects and gain good experience, deep thinking becomes essential in each case because there are always exceptions to any rule, so there are scenarios where the overhead of using async/await & threads may transcends their benefits. For example, Microsoft decided not to use it for the logger in ASP.Net Core and there is even a comment about it in the source code.
In your case, the webserver uses much more threads that you seem to think and for much more reasons than you seem to think. Also when a thread is idling waiting for something, it cannot do anything else. What async/await do is that they untie the thread from the current awaited task so the thread can go back to the pool and do something else. When the awaited task is finished, a thread (can be a different thread) is pulled out of the pool to continue the job. You seem to understand this to some degree, but perhaps you just don't know what other things a thread in a webserver can do. Believe me, there is a lot to do.
Finally, remember that threads are generic workers, they can do anything. Webservers may have specialized threads for different tasks, but they fall into two or three categories. Threads can still do anything within their category. Webservers can even move threads to different categories when required. All of that is done for you so you don't need to think about it in most cases and you can just focus on freeing the threads so the webserver can do its job.
Given the case there is only one thread for all requests / work.
I challenge you to say that this is a very abstruse case. Even before multi core servers because standard, asp.net used 50+ threads per core.
If this thread awaits a task it is not blocked but it also has no other work to do so it
just idles.
No, it goes back into the pool handling other requests. MOST web services will love handling as many requests as possible with as few resources as possible. Servers only handling one client are a rare edge case. Extremely rare. Most web services will handle as many requests as the plenthora of clients throw at them.

Thread Static, ASP.NET and Async handlers

Please consider these sceanrios:
An async .ashx handler
A async .asmx web-service method
A sync MVC 5 controller action method
I am trying to figure out a way to set "logical thread" specific data that can be accessed consistently during a "logical" http request, i.e. if the data was set on the thread in the "BeginExecute" part of which-ever async handler you would consider, that data is available in the "EndExecute" part of that asnc handler even if ASP.NET executes the "EndExecute" part on a different OS/.Net thread.
Moreover, I am expecting that the data set in the "BeginExecute" part on whatever OS/.Net thread it was on is NOT available on a subsequent http request if the second request is assigned the thread that was earlier assigned to first http request when it was in "BeginExecute" portion but this thread freed up as the first http request went in its async operation (and its possibly still completing its async operation).
I believe the word "logical thread" or "logical thread context" in .Net actually means the same "logical" flow of operation that I have mentioned (and not the underlying OS/.Net thread that keeps getting re-assigned). If you look at it from a workflow perspective, each http request is a new "logical" operation (even if multiple users invoke the same web-service sequentially or in parallel, each request is a new and separte logical operation), and in this meaning, the "logical" operation is one-time and cannot repeat. However the same underlying OS/.Net threads can be mapped to "logical" operations as they arrive based on their availability.
Additionally I want to expose this data as HttpContext.Current sort of static property. To some people this may come as a surprise, but HttpContext.Current does not work correctly if you are using for example async .asmx web-service methods. I am sure I have read content on web which says HttpContext.Current should always return correct HttpContext, but I have seen it as null in EndExecuteMethod of .asmx web-methods. It would be great if somecan can confirm if I am right in making my last statement, but this statement is not the overall question I am trying to ask here.
After reading a good amount of literature (e.g. What is the difference between log4net.ThreadContext and log4net.LogicalThreadContext?, http://msmvps.com/blogs/jon_skeet/archive/2010/11/08/the-importance-of-context-and-a-question-of-explicitness.aspx, http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html and more including MSDN docs), here are my inferences:
ThreadStatic is local to underlying OS/.Net thread and not to the "logical" operation, hence in my example; data set on first http request in "BeginExecute" would be visible in next http request if the second http request gets assigned the same thread as "BeginExecute" for first thread. And this data won't be available in "EndExecute" if it happens to be re-assigned to another thread by .Net (which would happen in vast majority of the cases).
Thread.SetData is even more problematic for my use-case. It needs data slots to be passed in and if I were to pass in a data slot from a return value of Thread.GetNamedDataSlot, the information is available across the app domain; as named data slots are shared between threads.
CallContext.SetData is like ThreadStatic (which means its not shared by app domain but different http requests would see the same data if they get assgined to the same underlying OS/.Net thread). CallContext.SetData provides an additional ability to marshal the context data for RPC calls which is irrelevant to the current question being asked.
Then there's the ThreadLocal class (.Net 4/.Net 4.5). It could have solved one part of my problem it seems, I could have passed it inside stateObject of BeingExecute operation, and extract from the same stateObject parameter of endExecute operation. From this perspective, ThreadLocal seems to be written for .Net's async support. But it won't work when I need to access it like HttpContext.Current as there's no way I can see to preserve the "logical thread static" instance ofit (unless I have said something incorrectly in my previous 3 points).
And finally it seems CallContext.LogicalSetData does what I intend to achive. Using the set of CallContext.LogicalSetData and CallContext.LogicalGetData methods, I should be able to achieve the HttpContext.Current like impact which works correctly for "logical task executions".
Now come the questions:
Is everything I have said above correct. Please correct any and all incorrect claims I have made.
Are there any other options available for thread static kind of feature in .Net that I missed.
Does CallContext.LogicalSetData/LogicalGetData pass on the context data to RPC calls (the msdn page does not mention clearly, http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.logicalsetdata(v=vs.110).aspx).
Are there any downsides (performance wise or otherwise) of using CallContext.LogicalSetData/LogicalGetData.
This page says something about copy-on-write behavior for LogicalSetData: http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html. In the context of async handlers/async MVC 5 action methods, what's the impact if I save a reference type using logicalsetdata and later change the state of the reference type. What are the repuccursions.
For mutation/logicalsetdata/async, I still can't see what's the problem by mutating the object. When the async method starts, the copy-on-write behavior would trigger a copy of context data the next time logicalsetdata is called. This is a shallow copy, so my reference object is now actually shared by 2 logical contexts and the changes in one context are visible in the other context which is what I would normally expect from a reference type.
A long question with lots of references, but hopefully I did my research well and the answers would benefit other people too.
I am trying to figure out a way to set "logical thread" specific data that can be accessed consistently during a "logical" http request
The only possible options are HttpContext.Current.Items and the logical CallContext.
Moreover, I am expecting that the data set in the "BeginExecute" part on whatever OS/.Net thread it was on is NOT available on a subsequent http request
HttpContext.Current.Items will always be cleared on a new request, but you'll have to clear the logical CallContext data yourself.
HttpContext.Current does not work correctly if you are using for example async .asmx web-service methods.
I find this surprising. I haven't tried it, but it should work - if you are running on .NET 4.5, targeting .NET 4.5 (i.e., have targetFramework set to 4.5 in your web.config), and aren't using async void.
[ThreadStatic], thread-local data slots, (non-logical) CallContext, and ThreadLocal are all thread-specific data, and will not work for asynchronous code.
Is everything I have said above correct. Please correct any and all incorrect claims I have made.
There is really way too much text in your question. Stack Overflow is a Q&A site, not a mentoring site.
Are there any other options available for thread static kind of feature in .Net that I missed.
No.
Does CallContext.LogicalSetData/LogicalGetData pass on the context data to RPC calls
I have no idea. Try it and see.
Are there any downsides (performance wise or otherwise) of using CallContext.LogicalSetData/LogicalGetData.
There's a definite performance hit. The .NET framework is highly optimized for the common case (no logical call context data).
what's the impact if I save a reference type using logicalsetdata and later change the state of the reference type.
The logical CallContext has shallow-copy-on-write behavior. So, any kind of asynchronous fork/join concurrency (i.e., Task.WhenAll) will end up sharing that state. If you use ConfigureAwait(false), you could also end up with race conditions.
To actually solve your problem, I recommend you first look into why HttpContext.Current doesn't work as expected; my guess (without seeing the project) is that targetFramework is set to 4.0 instead of 4.5. HttpContext.Current.Items is the most performant choice if you can get it working.

Using Async controller action to call existing synchronous method

I've not dealt much with Async/threads/Tasks other than some web services.
I'm using MVC4. I have existing code which takes some time to run. It is using an existing method in the service layer, which uses various other the areas in further layers.
Essentially I was hoping to be able to make an ASync call from the Asynccontroller to that method. However it appears that I would need to change/create another method to implement all the Task & await keywords, quite a hefty job altering all the way down the chain.
Is it possible to call/'fire' a synchronous method in this manner?
I want the long process (creating some documents in the background) to continue running even if the user closes their browser. However if the user still has the browser open then I would like to return a notification to them.
Is there a better way to fire a background task to execute from the MVC Application?
I think you're trying to use async for something it cannot do. As I describe on my blog, async does not change the HTTP protocol.
Is it possible to call/'fire' a synchronous method in this manner?
Sort of. You can use Task.Run if you have CPU-bound work that you want to move off the UI thread in a desktop/mobile application. But there is no point in doing that in an ASP.NET MVC application.
I want the long process (creating some documents in the background) to continue running even if the user closes their browser. However if the user still has the browser open then I would like to return a notification to them.
The problem with this is that you'd be returning early from an ASP.NET request, and (as I describe on my blog), that's quite dangerous.
A proper solution would be to queue the work in a reliable queue (e.g., Azure queue or MSMQ), have an independent backend for processing (e.g., Azure worker role / web job or Win32 service), and use something like SignalR for notification.
As soon as you attempt to do work in an ASP.NET process without a request context, then you run into the danger that your process may exit without completing the work. If you are OK with this, then you can use the BackgroundTaskManager type from my blog above to minimize the chance of that happening (but keep in mind: it can still happen).

Best practice to call ConfigureAwait for all server-side code

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.

CallContext vs ThreadStatic

What are differences between CallContext and ThreadStatic?
I've understood that in an ASP.NET environment data stored in CallContext could be persisted throughout the request until it ends while ThreadStatic may or may not work since the request may switch threads. I've also learned that the HttpContext is internally stored using the CallContext.
In a regular application they both seem to persist throughout the same thread call. When isn't this the case?
Edit: In the comments I learned that the call context is an abstraction over a thread static store. The ASP.NET framework explicitly moves the data from one thread to the next that is to handle one request. Other framework that wants to provide thread agility could do the same to for contextual storage.
Very often a request will use the same thread throughout, but it certainly won't always be the case - ASP.NET exhibits thread agility. There's an old in-depth blog article about the matter from 2005, but as of .NET 4.5 things are rather better.
Items stored as ThreadStatic are available to more than one request. IIS reuses the thread after a request is complete to process subsequent requests, it can even swap a request from one thread to another during processing. ASP.Net clears down the CallContext after each request.

Categories