HttpContext.Current在多线程环境下是如何工作的?

12

我一直在想,既然asp.net是多线程的,那么它是如何限定静态属性的作用域的。

  • 一个理论认为ASP.NET维护了每个请求的不同应用程序域...但这似乎不可行。
  • 另一个理论认为,.Current方法查看当前线程,然后使用它来查找某个哈希表(或其他静态存储机制)中的http上下文。

无论哪种方式,这似乎是一种非常有用的技术...我想利用它,但肯定不想调试共享状态错误 :-/

2个回答

15

这不是每个请求一个AppDomain。如果你想使用线程特定状态,请尝试:

[ThreadStatic]
private static int foo;
public static int Foo {get {return foo;} set {foo = value;}}

现在每个线程都有自己的Foo值(或者说是'foo')。

这并不是轻易使用的东西 - 它具有成本,但它是一种按线程共享状态的有效方式。我可能只使用过这个一两次 - 而我已经写了很多C#代码。不要过度使用它...

特别要注意初始化问题(即忘记进行初始化),并记得在使用完后清理自己等等。如果您使用任何异步代码,请非常小心,因为任何回调、工作线程等都将具有不同的状态。


太棒了,感谢这个……静态实例在线程结束后会被清除吗? - Joel Martinez
3
需要注意的是,在高负载情况下,[ThreadStatic]并不可靠。ASP.NET会在线程之间切换请求上下文并迁移HttpContext。任何[ThreadStatic]都将留在旧线程上,而旧线程正在处理一个新请求。 - Rex M
有趣的问题...特别是如果它是一个可能被重复使用的池线程 ;-p 我的建议:如果你正在做这种事情,就手动清理一下。 - Marc Gravell
@Rex M - 的确如此。上面的答案主要是为了指示您如何在常规代码中实现类似的效果。ASP.NET 在线程方面可能会有些奇怪 ;-p - Marc Gravell

8
马克所说的对于你想要的最简单,但ASP.NET实际上比ThreadStatic更复杂,因为单个请求实际上可以由多个线程处理。我认为在ASP.NET中发生的是执行线程被明确告知切换上下文,当然,托管环境正在调度线程并且它有需要执行的httpcontext的上下文,因此它找到一个线程,告诉线程应该在哪个上下文中运行,然后将其发送出去。

因此,解决方案实际上并不那么美好,而ThreadStatic则简单得多,可能95%的情况都适用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接