C#Singleton对象的许多实例

时间:2011-12-05 13:26:49

标签: c# singleton

我遇到了Singleton模式的问题。

这真的很奇怪,但看起来我的Singleton模式有两三个实例。 我的网站是一个行动网站,有计时器,我正在用我的Singleton对象处理这些计时器和价格。

发生的事情是,有些人看到了一些价格,而其他人在不同的网络中看到其他价格。

例如,在我的办公室,我的人看到一些0.56美分的拍卖,每个人都看到相同,但在另一个网络中,例如,我的房子,我看到0.55美分,而且计时器有不同的价值。

话虽如此,我已经通过生成GUID并将其记录在我的日志文件中来测试我的Singleton。这是一些代码

public class Singleton
{
    private static Singleton instance;
    private static System.Threading.Mutex mutex;

    System.Guid token;

    private Singleton() { 
        token = System.Guid.NewGuid();
        Logger.Log("New singleton Instance" + token.toString());
    }
    static Singleton()
    {
        instance = new Singleton();
        mutex = new System.Threading.Mutex();
    }

    public static Singleton Acquire()
    {
        mutex.WaitOne();
        return instance;
    }

    // Each call to Acquire() requires a call to Release()
    public static void Release()
    {
        mutex.ReleaseMutex();
    }

    public void SomeAction()
    {
       Logger.Log(token.toString() + " - SomeAction");
    }
}

在这段代码中,我在构造函数上生成令牌,并记录新Singleton的创建,然后在SomeAction方法中记录谁正在执行该操作。

在此之后,我们进行了几项测试并下载了日志文件。

令我惊讶的是,我只看到一个“New Singleton Instance bla”,这是正确的。但是,很多人使用不同的GUID调用SomeAction方法,这很奇怪。

我检查过该对象只在静态构造函数中创建,我还检查过在任何地方都没有手动创建。

有关详细信息,这只发生在我的生产服务器上,这是一个goDaddy托管。我问过我的网站是否有多个应用程序池,他们说只有一个应用程序池。

5 个答案:

答案 0 :(得分:4)

您的单身生命周期与IIS的当前工作进程相关联。

如果您配置了多个工作进程,那么并非所有请求都由同一进程处理,因此不是相同的单例。

答案 1 :(得分:2)

我不能肯定这是你的问题,但可能值得检查:

  • 如果在初始化日志记录框架之前创建实例,消息是否会被缓存,或者被丢弃?我已经看到过去的日志消息丢失了,因为它们是在初始化日志之前发生的。
  • 您是否可以引用包含此类的程序集的多个版本?这可能导致创建每个程序集版本的类的一个实例,因此看到的值将取决于调用它的代码。但是,这并不能解释从不同地理位置访问相同页面时您看到的不同值的行为。
  • 如果可以的话,我也会想要记录某种形式的unique machine id,以验证在一台计算机上只运行此代码的一个副本。当试图理解晦涩的行为时,“相信任何人,证明一切”是一个非常有用的启发式方法。

答案 2 :(得分:1)

您的网站可能只使用一个应用程序池,但应用程序池可能会产生多个主机进程。检查应用程序池的工作进程数。

答案 3 :(得分:1)

问题可能是您实施的单例模式不是线程安全的。 因为在Web应用程序中,您同时运行多个线程(工作进程),可能会发生两个线程创建两个不同的类实例。 您还应该考虑运行Web应用程序的位置。如果您在Web场上部署了Web应用程序,则可能会发生不同的Web服务器将您的类的不同实例作为静态变量“实时”存储在Web服务器的内存中。

答案 4 :(得分:0)

您的静态构造函数似乎不会检查是否已创建实例。类似的东西:

static Singleton()
    {
    if (instance == null)
        {
        instance = new Singleton();
        mutex = new System.Threading.Mutex();
        }
    }

应确保类中的其他方法实际使用instance的相同“实例”。