Safety of AsyncLocal in ASP.NET Core

后端 未结 2 863
温柔的废话
温柔的废话 2020-12-12 22:06

For .NET Core, AsyncLocal is the replacement for CallContext. However, it is unclear how \"safe\" it is to use in ASP.NET Core.

In ASP.NET 4 (MVC 5) and earlier, th

相关标签:
2条回答
  • 2020-12-12 22:27

    Adding my two cents if someone lands on this page (like I did) after googling if AsyncLocal is "safe" in ASP.NET classic (non Core) application (some commenters have been asking this, and also I see a deleted answer asking about the same).

    I wrote a small test that simulates asp.net's ThreadPool behavior

    1. AsyncLocal is always cleared between requests even if thread pool re-uses an existing thread. So it is "safe" in that regard, no data will be leaked to another thread.

    2. However, AsyncLocal can be cleared even within the same context (for example between code that runs in global.asax and the code that runs in controller). Because MVC-methods sometimes runs on a separate thread from non-MVC code, see this question for example: asp.net mvc 4, thread changed by model binding?

    3. Using ThreadLocal is not safe b/c it preserves the value after the thread from Thread Pool is re-used. Never use ThreadLocal in web-applications. I know the question is not about ThreadLocal I'm just adding this warning to whoever considering using it, sorry.

    Tested under ASP.NET MVC 5 .NET 4.7.2.

    Overall, AsyncLocal seems like a perfect alternative to short-time caching stuff in HttpContext.Current in cases where you can't access the latter directly. You might end up re-calculating the cached value a bit more often though, but that's not a big problem.

    0 讨论(0)
  • 2020-12-12 22:30

    I'm just looking into the source code of the ExecutionContext class for CoreClr: https://github.com/dotnet/coreclr/blob/775003a4c72f0acc37eab84628fcef541533ba4e/src/mscorlib/src/System/Threading/ExecutionContext.cs

    Base on my understanding of the code, the async local values are fields/variables of each ExecutionContext instance. They are not based on ThreadLocal or any thread specific persisted data store.

    To verify this, in my testing with thread pool threads, an instance left in async local value is not accessible when the same thread pool thread is reused, and the "left" instance's destructor for cleaning up itself got called on next GC cycle, meaning the instance is GCed as expected.

    0 讨论(0)
提交回复
热议问题