HttpModule在工作线程之间共享吗?

7

我需要锁定访问实例成员吗?

例如:

public class HttpModule : IHttpModule
{
    //...

    Dictionary<int, int> foo;

    void UseFoo(int a, int b)
    {
        foo[a] = b;
    }
}
4个回答

4
从MSDN文档上看,对我来说还不是很清晰,但我在论坛帖子中找到了一个声称知道答案的人。听起来你不应该期望你的实现出现问题,但你应该意识到foo的状态不一定会在所有结果中共享,因为你的HttpModule将会每个由IIS选择保留在其池中的HttpApplication中创建一次。

是的,它在许多不同的请求之间重用实例。但问题是它是否在不同的线程之间重用实例。 - TN.
1
据我所知:是的,但不能同时。一个HttpApplication似乎被分配给一个请求,在该请求的持续时间内。 - sblom
好的,谢谢。我会等待确切知道这个问题的人确认,因为我将在生产环境中使用该代码,并且很难调试。 - TN.

2

我想在这里提供与此问题相关的发现,因为我在IIS6中观察到:

我一直在处理这个问题,在使用log4net和反射捕获执行历史记录时发现了一些有趣的结果。我所发现的是,幕后进行了广泛的“线程管理”。似乎有一个“主”系列的线程与HttpApplication相对应。然而,这些线程并不专门处理您的请求的管道。当访问这些实例时,各种不同的子线程可以被调用。您的应用程序使用的随后的新请求和资源请求似乎共享与原始请求相关的一些持久信息,但始终没有完全由初始线程处理,这表明某种关系类型。我无法确定任何具体的模式(除了我之前描述的内容),以确定哪些元素被分配给其他线程,因为它似乎是随机的。根据这些证据,我的结论是,发生了某种层次池化的概念?其中某些未知的参考元素子线程通过父参考继承。

因此,我的答案是,HttpModules 在线程之间是共享的。就锁定实例值而言,如果这些值应用于使用模块的所有请求,并且必须维护某些状态,则这将是适用的。如果尝试维护昂贵的有状态实例值,以便在随后的请求中重用它们,则我可以看到这是有用的。

这个问题困扰了我一段时间,希望这些信息能帮助到某人。


1

我最近发现了一篇稍微涉及到这个问题的文章:

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; 
            } 
        } 
    } 
}

我一直想设置一个测试应用程序来运行和测试它,只是为了看看它是否真实,但我一直没有时间。


谢谢你的回答。这将检查它是否现在是共享的。我需要确切地知道它,因为正如我上面提到的,我将在生产环境中使用它,如果它发生变化,例如在.NET Framework或IIS的某些更新期间,那将会非常痛苦。 - TN.

1
Jim发布的文章很有趣,但正如Jim所说,它没有提及任何关于线程安全的内容。
我猜如果你正在初始化静态成员或执行“只需一次”初始化(即初始化静态资源),那么你只需要锁定机制。
我无法从MSDN或Jim提到的文章中得出结论,我们在初始化非静态类变量时需要锁机制。

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