We have multiple Http Modules in our ASP.NET application.
The modules are processing request and set some Thread Static variables.
However, sometimes it seems that the next Http Module in sequence is executed in a different thread than previous and the Thread Static variable is not set in such case.
Is there any way to guarantee that each Http Module will work in the same thread as previous.
Thanks
No, ThreadStatic should be avoided in an IIS context. Use HttpContext.Items instead. It is not possible to avoid the fact that IIS may serve a single request with multiple worker threads AFAIK. See, e.g. this Scott Hanselman blog post
Related
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.
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
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.
I have a RESTful C# web service (using Open Rasta) that I want to run IronPython scripts that talk to a CouchDB.
One thing I could use some clarification on is: How often do I need a new instance of the python engine and the scope? one each per application? per session? per request?
I currently have a static engine at the application level along with a dictionary of compiled scripts; then, per request, I create a new scope and execute the code within that scope...
Is that correct? thread safe? and as performant as it could be?
EDIT: regarding the bounty Please also answer the question I posed in reply to Jeff: Will a static instance of the engine cause sequential requests from different clients to wait in line to execute? if so I will probably need everything on a per-request basis.
A ScriptRuntime/ScriptEngine per application and a Scope per request is exactly how it should be done. Runtimes/Engine are thread-safe and Scopes are not.
Per request is the way to go unless all of your code is thread safe. You may get better performance using per application (per session implies you have th notion of "sesions" between you client and server), however the implication there is that all of your code in the "application" is thread safe.
So per-request is what you should use unless you know your code to be thread safe.
Note also that per application will be faster only if:
In order to make things thread safe
you've not blocking threads in any
way.
To a certain extent if the
business layer/data layer are
extremely "heavy" (take a lot of
time to instantiate) then some
performance benefit may be gained.
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.