如您所知,HttpContext.Current返回应用程序管道中的当前上下文
此属性也是static
,因此逻辑上对该属性或其属性的任何更改都应该影响其他管道。
静态字段确切地标识一个存储位置。不管怎样 创建了一个类的许多实例,只有一个副本 静态字段。 More
IIS如何处理此问题以防止其他管道发生冲突,并且每个管道上的每个HttpContext.Current
都是唯一的?
例如,对于已登录系统的两个用户,HttpContext.Current.User.Identity.Name
会将发送请求的用户的用户名提供给服务器。
ASP.NET管道:
答案 0 :(得分:7)
Current
是属性,而不是字段,所以它实际上是一个静态方法。
这个方法可以为不同的线程返回不同的实例,而且确实如此。
如果您正在开发多线程Web应用程序,请记住一些事项。
请勿使用ThreadStaticAttribute
。它适用于Windows和控制台应用程序,但它可能无法在Web应用程序中运行,因为如果您使用async
,await
和Task<T>
,则可以由不同的线程处理单个请求。
使用HttpContext.Current.Items
代替ThreadStaticAttribute
。这些Items
在每个HttpContext
中都是“静态的”。
如果您在异步调用后需要HttpContext
(区域设置,已记录用户和您自己的HttpContext.Items
)的重要设置(如果您不使用{{},请使用SynchronizationContext {1}})。
你应该小心的原因是一个线程池。您的异步方法很可能开始在第一个线程中运行,在一秒钟内继续运行,在第三个线程中结束。由于每个线程都有自己的线程静态字段副本,因此您可以在方法的不同位置获得不可预测的不同字段值。 await
允许您使用正确的区域设置值SynchronizationContext
等返回初始线程。HttpContext.Items
运算符可以帮助您,因此您不应该关心上下文,如果您正在使用await
(感谢@StephenCleary进行更正)。
现在为线程静态字段。当ASP.NET获取HTTP请求时,它会创建具有空await
集合的HttpContext
的新实例。同时,先前的HTTP请求已初始化HttpContext.Items
个字段。因此f.e.基于线程静态字段的ThreadStatic
类可能无法正常工作。它在Web应用程序的同步和异步方法中都很重要。
答案 1 :(得分:4)
答案在于线程本地存储,在.NET中使用ThreadStatic
实现。环境上下文设计模式也与此相关。