【发布时间】: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