HttpContext.Current 如何处理 IIS 管道中的每个请求?
How HttpContext.Current works on each request in IIS pipeline?
如您所知,HttpContext.Current returns 应用程序管道中的当前上下文。
此外,此 属性 是 static
,因此从逻辑上讲,对其或其属性的任何更改都应影响其他管道。
A static field identifies exactly one storage location. No matter how
many instances of a class are created, there is only ever one copy of
a static field.
More
IIS 如何处理此问题以防止在其他管道上发生冲突并且每个 HttpContext.Current
在每个管道上都是唯一的?
例如,对于已经登录系统的两个用户,HttpContext.Current.User.Identity.Name
给出向服务器发送请求的用户的用户名。
ASP.NET管道:
Current
是属性,不是字段,所以它实际上是一个静态方法。
此方法可以 return 不同线程的不同实例,而且确实如此。
如果您正在开发多线程 Web 应用程序,请记住以下几点。
不要使用 ThreadStaticAttribute
。它适用于 Windows 和控制台应用程序,但它可能不适用于 Web 应用程序,因为单个请求可以由不同的线程处理,如果您使用 async
、await
和 Task<T>
.
使用 HttpContext.Current.Items
而不是 ThreadStaticAttribute
。这些Items
在每个HttpContext
中是"static"。
如果您在异步调用后需要 HttpContext
的重要设置(区域设置、登录用户和您自己的 HttpContext.Items
),请使用 SynchronizationContext(如果您没有使用 await
).
你要小心的原因是线程池。您的异步方法很可能在第一个线程中开始 运行,在第二个线程中继续,并在第三个线程中结束。由于每个线程都有自己的线程静态字段副本,您可以在方法的不同位置获得不可预知的不同字段值。 SynchronizationContext
允许您 return 使用正确的区域设置值 HttpContext.Items
等初始线程。 await
运算符对您有用,所以您不应该关心上下文,如果你使用 await
(感谢@StephenCleary 的更正)。
现在是线程静态字段。当 ASP.NET 收到 HTTP 请求时,它会创建带有空 HttpContext.Items
集合的 HttpContext
的新实例。同时 ThreadStatic
字段已由先前的 HTTP 请求初始化。因此f.e。 a Singleton
class,基于线程静态字段可能无法正常工作。它在 Web 应用程序的同步和异步方法中都很重要。
答案在于线程本地存储,在 .NET 中使用 ThreadStatic
实现。环境上下文设计模式也与此相关。
如您所知,HttpContext.Current returns 应用程序管道中的当前上下文。
此外,此 属性 是 static
,因此从逻辑上讲,对其或其属性的任何更改都应影响其他管道。
A static field identifies exactly one storage location. No matter how many instances of a class are created, there is only ever one copy of a static field. More
IIS 如何处理此问题以防止在其他管道上发生冲突并且每个 HttpContext.Current
在每个管道上都是唯一的?
例如,对于已经登录系统的两个用户,HttpContext.Current.User.Identity.Name
给出向服务器发送请求的用户的用户名。
ASP.NET管道:
Current
是属性,不是字段,所以它实际上是一个静态方法。
此方法可以 return 不同线程的不同实例,而且确实如此。
如果您正在开发多线程 Web 应用程序,请记住以下几点。
不要使用
ThreadStaticAttribute
。它适用于 Windows 和控制台应用程序,但它可能不适用于 Web 应用程序,因为单个请求可以由不同的线程处理,如果您使用async
、await
和Task<T>
.使用
HttpContext.Current.Items
而不是ThreadStaticAttribute
。这些Items
在每个HttpContext
中是"static"。如果您在异步调用后需要
HttpContext
的重要设置(区域设置、登录用户和您自己的HttpContext.Items
),请使用 SynchronizationContext(如果您没有使用await
).
你要小心的原因是线程池。您的异步方法很可能在第一个线程中开始 运行,在第二个线程中继续,并在第三个线程中结束。由于每个线程都有自己的线程静态字段副本,您可以在方法的不同位置获得不可预知的不同字段值。 SynchronizationContext
允许您 return 使用正确的区域设置值 HttpContext.Items
等初始线程。 await
运算符对您有用,所以您不应该关心上下文,如果你使用 await
(感谢@StephenCleary 的更正)。
现在是线程静态字段。当 ASP.NET 收到 HTTP 请求时,它会创建带有空 HttpContext.Items
集合的 HttpContext
的新实例。同时 ThreadStatic
字段已由先前的 HTTP 请求初始化。因此f.e。 a Singleton
class,基于线程静态字段可能无法正常工作。它在 Web 应用程序的同步和异步方法中都很重要。
答案在于线程本地存储,在 .NET 中使用 ThreadStatic
实现。环境上下文设计模式也与此相关。