Safety of AsyncLocal in ASP.NET Core
在ASP.NET MVC(4和5)前,ASP.NET线程模型
在对比,在欧文的上下文/武士刀的Web API的线程模型,敏捷性,需要的是什么问题。我可以安全地使用后小心CallContext,考虑到如何正确的处理它。
但现在我与ASP.NET的核心处理。我想用下面的中间件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public class MultiTenancyMiddleware { private readonly RequestDelegate next; static int random; private static AsyncLocal<string> tenant = new AsyncLocal<string>(); //This is the new form of"CallContext". public static AsyncLocal<string> Tenant { get { return tenant; } private set { tenant = value; } } //This is the new verion of [ThreadStatic]. public static ThreadLocal<string> LocalTenant; public MultiTenancyMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { //Just some garbage test value... Tenant.Value = context.Request.Path + random++; await next.Invoke(context); //using (LocalTenant = new AsyncLocal<string>()) { // Tenant.Value = context.Request.Path + random++; // await next.Invoke(context); //} } } |
到目前为止,上面的代码似乎工作只是罚款。但至少有一个红色的标志。在过去,它是关键,确保
现在我没有自明湖路
1包括该代码,显示出知识,
这是因为还没有
即使是在我
特别注
对于那些有问题的unfamiliar
此外,我可以亲自证明这不幸的行为。当我建立ASP.NET应用程序,我的一部分。通常包括负载测试的自动化测试基础设施。它是在负载测试,我可以变得不稳定,也见证
然而,在ASP.NET核心案例,我无法在没有httpcontext.items依赖静态...there搜索接入点。我现在还没有可以创建负载测试.NET应用程序的核心tinkering I’M个部分,这是为什么我不回答这个问题是我自己。:)
Again: Please understand that the"instability" and"problem" I'm discussing is not a bug at all. CallContext is not somehow flawed. The issue is simply a consequence of the thread dispatch model employed by ASP.NET. The solution is simply to know the issue exists, and to code accordingly (e.g. use
HttpContext.Current.Items instead ofCallContext , when inside an ASP.NET app).
我的目标是了解如何这一问题在动态(或不)适用于ASP.NET的核心,所以我不小心当使用新的代码生成不稳定的
我只是在研究corecrl的executionContext类的源代码:https://github.com/dotnet/corecrl/blob/775003a4c72f0acc37eab84628fcef541533ba4e/src/mscorlib/src/system/threading/executioncontext.cs
根据我对代码的理解,异步本地值是每个ExecutionContext实例的字段/变量。它们不基于线程本地或任何线程特定的持久化数据存储。
为了验证这一点,在我的线程池线程测试中,当重用同一个线程池线程时,将无法访问异步本地值中的一个实例,并且在下一个GC循环中调用了用于清除自身的"左"实例的析构函数,这意味着该实例将按预期进行gced。