Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Is Asp.net Core Thread-agile with Kestrel behind IIS? #1371

Closed
FlorianRainer opened this issue Mar 30, 2016 · 6 comments
Closed

Question: Is Asp.net Core Thread-agile with Kestrel behind IIS? #1371

FlorianRainer opened this issue Mar 30, 2016 · 6 comments

Comments

@FlorianRainer
Copy link

I'm digging around already for some days to figure out how to replace the "System.Web.HttpContext.Current.Items" Collection used in my .Net 4.6 WebApi.
I can't rewrite it from scratch for this i need a static collection to set values for each request.

I have made some Tests with [ThreadStatic] Properties and it seems to work on my local IIS Express.
But i know there was always a problem on Asp.Net if you use [ThreadStatic] if IIS migrates the request from one Thread to another.

But now IIS is forwarding the Requst to a DNX process and the Request will be processed by "Kestrel" (i think)

Can anyone tell me how the Thread Pooling works now?
Is Kestrel doing it the same way as IIS does?
Are Requests still migrated between Threads, or are the assigned to one Thread?
Can we use [ThreadStatic] now or is there any replacement for the System.Web.HttpContext.Current.Items Collection?

@davidfowl
Copy link
Member

Is Asp.net Core Thread-agile with Kestrel behind IIS?

Yes, requests can hop threads. Whether it's behind IIS is irrelevant.

I have made some Tests with [ThreadStatic] Properties and it seems to work on my local IIS Express.
But i know there was always a problem on Asp.Net if you use [ThreadStatic] if IIS migrates the request from one Thread to another.

Write some async code and it'll stop working 😄 .

Can anyone tell me how the Thread Pooling works now?

Same as before.

Is Kestrel doing it the same way as IIS does?

It's not really IIS, it's the .NET thread pool. Kestrel has dedicated IO threads but user code never runs on them. User code always runs on various thread pool threads.

Are Requests still migrated between Threads, or are the assigned to one Thread?

See above answer.

Can we use [ThreadStatic] now or is there any replacement for the System.Web.HttpContext.Current.Items Collection?

No, you can't safely use [ThreadStatic] for async code. There's no concept of "Current" request in ASP.NET Core (we don't like statics anymore). You can use the dependency injection friendly IHttpContextAccessor (if you register it with the service collection). You may also want to consider the new AsyncLocal<T> type that is like thread static but is stored in the execution context and thus flows across async calls http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html.

@FlorianRainer
Copy link
Author

thanks @davidfowl AsyncLocal<T> was exactly what i was looking for.
i have tryed to refactor the application to remove statics and use only registred services but ATM this would be to much work. AsyncLocal is a good workaround for me.

@joelharkes
Copy link

We have a project where we use AsyncLocal<Dictionary> quite heavenly.

It all seems fine when running locaclly but when we migrate the code to dotnet 1.1 runtime docker container we get a lot of errors when we start running multiple concurrent requests (a few single requests is fine but having like 10 requests a seconds it starts throwing errors) Any idea where i can start looking to fix this?

@FlorianRainer
Copy link
Author

If your Dictionary contains reference types (objects) only the reference whould be stored in the AsyncLocal if you modify values of this objects its working similar to static and needs locking or other threadsafe handling.

if you are using a Dictionary<string, string> it should be no problem

@joelharkes
Copy link

Yes i understand, but it seems not to be locking i'm getting null reference errors like it looks like a key is not set, even though earlier in the request pipeline i have added it.

@FlorianRainer
Copy link
Author

As far as i know AsyncLocal works only correct if the object used for AsyncLocal is Immutable.
It should be set on the start but never changed / added during the request. because each time you make a async call the object will be copied. if you add a value to this copy it will not return this modification back from this async context. and in your next async call you will not get the added key.

You can make a Workaround by making a class with one readonly property for your dictionary.
in this case only the reference whould be copied, but not the dictionary it self. this will allow you to add values in other async context or threads. BUT: remember to make it threadsafe or use ConcurrentDictionary

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants