2011-12-05 78 views
10

我遇到了Singleton模式的問題。C#Singleton對象的許多實例

這真的很奇怪,但它看起來像我的單例模式的兩個或三個實例。 我的網站是一個動作網站,帶有定時器,我正在用我的Singleton對象處理這些定時器和價格。

正在發生的事情是,有些人看到一些價格,而其他人在不同的網絡中總是看到其他價格。例如,在我的辦公室裏,我的員工看到0.56美分的拍賣會,每個人看到的都是相同的,但在另一個網絡中,例如我的房子,我看到0.55美分,而且定時器的價值也不同。在說了這些之後,我測試了我的Singleton,通過生成一個GUID並將其記錄到我的日誌文件中。下面是一些代碼

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

在這段代碼中,我生成構造器的令牌,並記錄新辛格爾頓的創建,然後......在SomeAction方法,我記錄誰在做這個動作。

之後,我們做了一些測試並下載了日誌文件。

令我驚訝的是,我看到只有一個「新的單身實例bla」,這是正確的。但隨後,許多用不同的GUID調用SomeAction方法,這很奇怪。

我檢查到,該對象只在靜態構造函數中創建,並且我還檢查了沒有手動創建任何地方。

欲瞭解更多信息,這隻發生在我的生產服務器,這是一個goDaddy託管。我問過我的網站是否有多個應用程序池,並且他們說只有一個應用程序池。

+6

嘗試按照建議實施你的單身人士[這裏](http://csharpindepth.com/Articles/General/Singleton.aspx)。 –

+0

我在想爲什麼你創建了靜態構造函數? – FosterZ

+0

也許你可以使用一些Dispose日誌記錄和添加TryCatch來診斷問題。祝你好運。 – CodingBarfield

回答

4

您的單身生命週期與IIS的當前工作進程綁定在一起。

如果您配置了多個工作進程,那麼並非所有的請求都由相同的進程處理,因此不是相同的單例。

+0

這是有道理的,我會檢查有多少工作進程,我有...如果我有多個,你知道我怎麼能共享相同的單例實例嗎?可能嗎? – varholl

+0

這確實是我的問題,因爲有多個工作進程我有多個單例對象...可悲的是,我不能使用任何同步方法,因爲我不能使用消息隊列或遠程處理.. 。我試圖看看如果我每5秒鐘就可以同步一次,但在某些情況下......這是太多時間來等待:( – varholl

0

看來你的靜態構造函數不檢查是否已經創建實例。喜歡的東西:

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

應確保在類中的其他方法實際使用的instance相同的「實例」。

+4

-1:這是[靜態構造函數](http://msdn.microsoft.com/en-us/library/k9x6w0hc%28v=VS.100%29的.aspx)。它只執行一次... –

+0

同樣:靜態構造函數只執行一次。 –

+0

靜態構造函數(http://msdn.microsoft.com/en-us/library/k9x6w0hc%28v=VS.100%29.aspx)只執行一次。請看Jon Skeet關於實現Singletons的文章(http://www.csharpindepth.com/Articles/General/Singleton.aspx)。 –

2

我不能肯定地說,這是你的問題,但它可能是值得檢查:如果你的日誌框架被初始化之前創建一個實例

  • ,並在消息獲取緩存,或者只是扔掉?我以前看過日誌消息丟失了,因爲它們在日誌記錄初始化之前發生。
  • 是否有可能引用包含此類的程序集的多個版本?這可能會導致每個程序集版本的類的一個實例被創建,因此所看到的值將取決於調用它的代碼。但是,這並不能解釋您在訪問來自不同地理位置的相同頁面時看到的不同值的行爲。
  • 如果可以的話,我也會試圖登錄某種形式的unique machine id,以驗證在一臺機器上只能運行此代碼的一個副本。 「不信任任何人,證明一切」在嘗試理解模糊行爲時是非常有用的啓發式。
+0

感謝您的回覆!我會檢查日誌初始化,因此可能會丟失這些消息。 是否有可能在bin目錄中有多個相同的dll版本?我的意思是我的所有dll都放在我的bin文件夾中,而不是GAC。 – varholl

+0

我相信可以從同一個目錄加載同一個程序集的多個版本,但是重命名文件需要一些技巧,所以你不太可能不小心做到了。 –

1

您的網站可能只能使用一個應用程序池,但應用程序池可能會產生多個主機進程。檢查您的應用程序池的工作進程數量。

1

這個問題可能是你已經實現的單例模式不是線程安全的。 ,因爲在一個web應用程序中,你有多個線程同時運行(工作進程),可能會發生兩個線程創建兩個不同類的實例。 您還應該考慮您的網絡應用在哪裏運行。如果您在網上服務器上部署了您的Web應用程序,則可能發生這樣的情況:不同的Web服務器將類的另一個實例作爲Web服務器內存中的「活動」靜態變量。

+0

感謝您的回覆,在我的日誌文件中,我看到不同的線程ID共享相同的令牌,所以我不認爲這是一個線程問題。我也確保通過使用鎖和互斥體幾乎無處不在線程安全!無論如何,我會進一步檢查,以確保它是線程安全的 – varholl

+0

也檢查Web應用程序是否部署在網絡農場。在這種情況下,你將有一個每個Web服務器的實例 –