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

Created on 30 Mar 2016  路  6Comments  路  Source: dotnet/aspnetcore

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?

Most helpful comment

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 :smile: .

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.

All 6 comments

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 :smile: .

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.

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.

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?

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 it should be no problem

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.

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

Was this page helpful?
0 / 5 - 0 ratings