【问题标题】:HttpApplication events changing threadsHttpApplication 事件改变线程
【发布时间】:2014-06-06 13:44:57
【问题描述】:

为了记录 ASP.NET Web 应用程序的目的,我将一些状态信息保存在一个静态类中。这些字段标记为[ThreadStatic],因此每个线程都有自己的字段副本。从 HttpApplication 事件方法调用日志记录方法:

  • Application_BeginRequest(请求开始,初始化状态)
  • Application_AcquireRequestState(会话和用户已知)
  • Application_EndRequest(请求结束,清理)

我现在可以观察到,在某些情况下,页面请求是在不同的线程中处理的。 BeginRequest 事件在线程 18 上运行,而以下事件在线程 4 上运行。当然,我的线程静态数据不可用并且发生错误。

大多数情况下,这工作得很好,每个请求都只在一个线程中处理。但是,当我请求加载约 5 秒的页面并在 1-2 秒后单击另一个链接时,两个请求并行运行。第一个在 5 秒后在线程 24(它也启动了)上完成,而另一个在线程 18 上启动,但在第一个请求完成后,第二个继续在线程 4 上运行。

尝试使用 3 个重叠的长请求,这纯粹是混乱。我什至可以看到两个请求在同一个线程上开始,而它们随后在不同的线程上继续。请求和线程之间似乎没有任何关系。

一个请求怎么会改变线程?如果它决定转移到另一个线程,它就会失去所有的状态。我能找到的每一个描述都表明这一切都发生在一个线程中。

IIS 7、Windows Server 2008 R2、x64 上的 ASP.NET 4.0。

替代方案:如果我不能依赖从头到尾仅在单个线程中处理请求,那么存储少量每个请求数据的最佳位置是什么(目前一个整数和一个类)访问速度非常快?并且最好在不引用 System.Web 的情况下也可以工作(我的代码也针对客户端配置文件)。我知道HttpContext.Current.Items[key],但它在远程处理程序集的某个深处进行了查找,并且涉及一个似乎比线程静态字段慢得多的字典。

【问题讨论】:

  • 你在哪里看到过只使用一个线程的保证?
  • 我现在找不到任何参考资料,但在我读到它是如何工作的任何地方,他们都说每个请求都运行在一个现有的 HttpApplication 实例上,这些实例都在自己的线程中运行。跨度>
  • 这里有一个参考:“实际上,在任何给定时间,都有多个 HttpApplication 实例处于活动状态,具体取决于应用程序的负载,每个实例在其自己的单独线程上处理请求。” (weblog.west-wind.com/posts/2009/Jun/18/…)
  • 您注意到参考日期了吗?五年前可能是这样。此外,这表示“他们自己的单独线程”,而不是“他们自己的专用线程”。
  • HttpContext.Current.Items[key]支持的方式来做你想做的事。除非您已经测试过seems a lot slower than a thread-static field 或确实有问题,否则您似乎正在走入预优化的兔子洞。

标签: asp.net .net multithreading


【解决方案1】:

ASP.NET 是thread agile,一个请求可以在多个线程上处理(但一次不能超过一个)。因此,您真的不能在 ASP.NET 中使用 ThreadStatics。但是,您可以安全地使用 HttpContext.Items 字典来存储需要限定为单个请求的内容。

要允许您的代码在 ASP.NET 应用程序的上下文之外工作,您可以创建一个交换 HttpContext / CallContext 的包装器,具体取决于代码所在的环境。Here is an example of such a wrapper

【讨论】:

  • 不仅如此,线程还可以被新请求重用。 (线程池)。这是在 ASP.NET 中永远不要使用 ThreadStatic 的一个更重要的原因
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2014-02-12
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多