我需要锁定访问实例成员吗?
例如:
public class HttpModule : IHttpModule
{
//...
Dictionary<int, int> foo;
void UseFoo(int a, int b)
{
foo[a] = b;
}
}
我需要锁定访问实例成员吗?
例如:
public class HttpModule : IHttpModule
{
//...
Dictionary<int, int> foo;
void UseFoo(int a, int b)
{
foo[a] = b;
}
}
我想在这里提供与此问题相关的发现,因为我在IIS6中观察到:
我一直在处理这个问题,在使用log4net和反射捕获执行历史记录时发现了一些有趣的结果。我所发现的是,幕后进行了广泛的“线程管理”。似乎有一个“主”系列的线程与HttpApplication
相对应。然而,这些线程并不专门处理您的请求的管道。当访问这些实例时,各种不同的子线程可以被调用。您的应用程序使用的随后的新请求和资源请求似乎共享与原始请求相关的一些持久信息,但始终没有完全由初始线程处理,这表明某种关系类型。我无法确定任何具体的模式(除了我之前描述的内容),以确定哪些元素被分配给其他线程,因为它似乎是随机的。根据这些证据,我的结论是,发生了某种层次池化的概念?其中某些未知的参考元素子线程通过父参考继承。
因此,我的答案是,HttpModules
在线程之间是共享的。就锁定实例值而言,如果这些值应用于使用模块的所有请求,并且必须维护某些状态,则这将是适用的。如果尝试维护昂贵的有状态实例值,以便在随后的请求中重用它们,则我可以看到这是有用的。
这个问题困扰了我一段时间,希望这些信息能帮助到某人。
我最近发现了一篇稍微涉及到这个问题的文章:
http://www.dominicpettifer.co.uk/Blog/41/ihttpmodule-gotchas---the-init---method-can-get-called-multiple-times它没有提到线程,但是只是说工作进程会实例化尽可能多的HttpApplication对象,然后出于性能原因将它们池化,重用实例以在新请求进来之前将它们发送回池中。
通过从链接中跟踪代码,您可以确保您的初始化代码以线程安全的方式执行一次:
private static bool HasAppStarted = false;
private readonly static object _syncObject = new object();
public void Init(HttpApplication context)
{
if (!HasAppStarted)
{
lock (_syncObject)
{
if (!HasAppStarted)
{
// Run application StartUp code here
HasAppStarted = true;
}
}
}
}
我一直想设置一个测试应用程序来运行和测试它,只是为了看看它是否真实,但我一直没有时间。