对于ASP.NET Web应用程序的日志记录,我将一些状态信息保存在静态类中。这些字段标记为[ThreadStatic]
,因此每个线程都有自己的字段副本。记录方法是从HttpApplication事件方法调用的:
我现在可以观察到,在某些情况下,页面请求在不同的线程中处理。 BeginRequest事件在线程18上运行,而以下事件在线程4上运行。当然,我的线程静态数据不可用,并且发生错误。
大多数情况下,此工作正常,每个请求仅在单个线程中处理。但是当我请求加载约5秒的页面并且在1-2秒之后单击另一个链接时,两个请求并行运行。第一个是在第4个线程(它也已经启动)在5秒后完成,而另一个在线程18上启动,但在第一个请求完成后,第二个请求继续在线程4上运行。
尝试使用3个重叠的长请求,这是一个纯粹的混乱。我甚至可以在同一个线程上看到两个请求,而后来每个请求继续在不同的线程上。似乎在请求和线程之间没有任何关系。
请求如何改变线程?如果它决定转移到另一个线程,它将失去所有状态。我能找到的每一个描述都表明这一切都发生在一个线程中。
IIS 7,Windows Server 2008 R2,x64上的ASP.NET 4.0。
替代方案:如果我不能依赖从头到尾只在一个线程中处理的请求,那么存储少量每个请求数据的最佳位置(目前一个可以非常快速访问的整数和一个类?并且最好也可以在不参考System.Web的情况下工作(我的代码也是针对客户端配置文件)。我知道HttpContext.Current.Items[key]
,但它在远程处理程序集的某处深处查找,并且涉及一个字典,它似乎比线程静态字段慢很多。
答案 0 :(得分:4)
ASP.NET是thread agile,并且可以在多个线程上处理请求(但不能超过一个)。因此,你真的不能在ASP.NET中使用ThreadStatics。但是,您可以安全地使用HttpContext.Items字典来存储需要作用于单个请求的内容。
要允许您的代码在ASP.NET应用程序的上下文之外工作,您可以创建一个交换HttpContext / CallContext的包装器,具体取决于代码所在的环境。Here is an example of such a wrapper。