【问题标题】:Singleton's running on Asp.Net web applicationsSingleton 在 Asp.Net 上运行的 web 应用程序
【发布时间】:2010-12-10 16:39:20
【问题描述】:

我有一个关于在 IIS (6,7,7.5) 和 ASP.NET 4.0 Web 应用程序(具体来说是 MVC3 应用程序)中运行的单例的问题。

我的项目中有一个单例对象,可以在 global.ascx、application_start 以及应用程序中的其他一些地方访问和使用它。

我担心的是,这个单例需要在每个实例场景中都可以访问。但是,由于 IIS 本质上是托管进程,那么单例是否会在应用程序的所有实例中成为同一个对象?

如果我使用 [ThreadStatic] 关键字,它是否在应用程序池级别分开?

最后,有没有办法,我可以保证单例只是我的应用程序的每个实例的单例。即,如果我在 1 个网站上运行我的应用程序,但在 5 个虚拟目录中,则有 5 个单例实例,或者如果我在同一应用程序池中的 5 个不同网站上运行我的网站。

希望这已经足够清楚了,如果您想查看单例对象,我将其大致概念粘贴在下面。

public sealed class Singleton : IDisposable
{
    [ThreadStatic]
    private static volatile Singleton _instance;
    [ThreadStatic]
    private static readonly object _syncRoot = new object();

    public bool IsReleased { get; private set; }

    public Singleton()
    {
        IsReleased = false;
    }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_syncRoot)
                {
                    if (_instance == null)
                        _instance = new Singleton();
                }
            }

            return _instance;
        }
    }

    public void Dispose()
    {
        IsReleased = true;
        Singleton._instance = null;
    }
}

【问题讨论】:

  • 我还是一头雾水。你知道它是如何工作的还是你不知道?你能把问题说清楚一点吗?
  • 我知道单例如何在每个进程级别“工作”。问题是 IIS 如何在我的应用程序的多个实例中处理它。
  • 只是出于好奇,为什么你的单身人士是一次性的?您是否希望有一段时间希望将其处理掉,然后在有人要求时再次将其复活?在应用程序终止之前,通常不会释放真正的单例。
  • 我相信 OP 的问题不清楚,因为他需要阅读 IIS 和回发。一般来说,单例与单个回发无关,而是跨多个回发。因此,仅在会话/视图状态方面讨论单例是相关的。 Viewstate 的定义非常明确,但网络花园和回收时间等复杂且可配置的元素开始发挥作用,尤其是因为 OP 提到了 w3wp.exe。我相信 OP 只需要阅读这些功能,但要从 ASP.NET 生命周期开始。然后进入多线程/公寓/进程。
  • @P.Brian.Mackey:他的问题有什么不清楚的地方?他不是在问单例是否会在多个回发中持续存在,而是在问它是否会在他的 Web 应用程序的多个实例中持续存在。由于 IIS 在单个进程中运行,他能否期望在不同的应用程序实例中拥有他的静态变量的不同实例?

标签: c# asp.net iis


【解决方案1】:

静态值在您的 Web 应用程序的特定实例中应该是静态的,因此您的应用程序的每个实例都有自己的实例,该实例将在该实例上的所有线程之间共享。

如需进一步阅读,请参阅http://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.71).aspx

哦,ThreadStatic attribute 将导致静态值仅在特定线程中是静态的,因此每个请求都有自己的该字段版本。听起来这不是你想要的。

【讨论】:

  • 我明白了,这或多或少是 IIS 控制实例的方式。由于您的应用程序在 IIS 的控制下运行,这本质上是控制进程 (w3wp.exe),因此,如果我们有 5 个实例正在运行,我们会遇到单例在这 5 个实例之间分离的问题,因为它们都在 w3wp.exe 下运行.
  • @John:来自引用的文章,“您可以在单个进程中运行多个应用程序域,并且具有与单独进程中存在的相同级别的隔离。”所以 IIS 有一个进程,但它在自己的应用程序域中运行每个应用程序实例,因此像类加载这样的事情将被视为每个应用程序都是一个独立的应用程序,与其他应用程序完全隔离。
  • 那么,您 100% 确定 IIS 将在单独的应用程序域中运行 5 个不同的虚拟目录,即使使用相同的应用程序池?
  • @John:不,我还没有真正使用过虚拟目录。但是,我们在同一个 IIS 实例上运行同一个 Web 应用程序的多个版本,它们的行为方式与我描述的一样。我假设虚拟目录的工作方式相同。但是测试起来很容易:创建一个非常简单的应用程序,每次加载页面时都会增加一个静态计数器,设置 IIS 以在两个不同的虚拟目录中运行该应用程序,并观察它们是否使用相同的计数器您从两个目录加载页面。
  • 我将不得不这样做,我避免的唯一原因是我现在没有真正的 IIS 环境(只有 Web 开发服务器)。不过,看来我得尽快找到一个了,我会用结果更新帖子并感谢您的建议。
【解决方案2】:

使用 IIS,您无法控制运行请求的线程。如果您确实需要这种应用程序实例级别的锁定,您可能需要查看更重的锁定对象(Mutex、Monitor 等)并为每个应用程序创建一个。

【讨论】:

    【解决方案3】:

    如果您绝对想确保它们是分开的,您可以在它自己的应用程序池中运行每一个。这样你就可以为每个虚拟目录获得一个 WP。

    【讨论】:

    • 为什么是-1?这不起作用吗?如果没有,我想知道以供我自己将来参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2014-08-22
    • 2012-08-04
    • 2015-11-12
    • 2010-10-18
    • 1970-01-01
    相关资源
    最近更新 更多