2012-07-06 64 views
1

我現在有一個事件處理器類,它有一個字典來存儲所有的訂閱。實際上它是一本字典詞典。此進程類正在與第三方遠程服務器進行通信,以提出對目標數據的請求。我在問這個問題,因爲現在我們遇到了偶爾訂閱丟失的問題。由於某種原因,很難驗證這種丟失是否發生在與遠程服務器的連接中,我現在必須首先檢查我的事件處理器類是否有任何問題。而且我的第一個嫌疑人是因爲這個Dictionary對象溢出而導致訂閱信息丟失。有人有什麼主意嗎?謝謝!.NET Dictionary對象可能溢出嗎?

UPDATE

也許我應該告訴多一點有關場景,因爲代碼是不是真的很容易顯現。我們曾經使用我們的傳統軟件(我們稱之爲A),使用B供應商提供的API與遠程數據服務(稱爲B)進行通信。但是,由於我們將A更改爲64位SW,但爲B提供的庫仍爲32位,因此我們的新64位A不能再使用此庫。所以我正在設計一個名爲C的32位SW,使用該庫連接到B,同時使用WCF保持與64位A的通信。由於C主要是pub/sub結構,正如我之前提到的,我正在使用Dictionary Dictionary來維護C中的請求和訂閱。而我們的問題就出現了:我們遇到了一些訂閱丟失(長時間沒有發佈,但在重新初始化訂閱後,我們可以在A處獲得這些出版物)。我們很難檢查B的反饋以查看是否存在任何錯誤配置。而我的WCF服務日誌也沒有顯示任何錯誤。我不得不懷疑這個問題只發生在C上。我意識到多線程問題,所以我鎖定了Dictionary的每一個操作。但我無法想象可能會出現什麼問題。順便說一句,它不像C,內存用完了,C崩潰了。

+0

你在服務器上發生溢出錯誤嗎?你爲什麼會認爲這是第一個罪魁禍首?這似乎不像一個似乎合理的探索 – 2012-07-06 19:04:21

+0

@RyanBennett請參閱我的更新。謝謝! – tete 2012-07-07 21:48:40

回答

6

如果通過「溢出」,你的意思是「默默地丟失數據」然後不,我不知道。

如果你的意思是「用盡系統中的所有內存,直到它崩潰」,那麼是的,這是可能的,但它聽起來不像你正在發生的事情。

如果您在多個線程中使用標準Dictionary<,>而沒有任何鎖定,那麼可能會導致您丟失數據。您應該使用鎖(小心!),或使用ConcurrentDictionary<,>如果你使用.NET 4

另外,如果你有,你沒有想到任何重複鍵,這將覆蓋的數據一個條目與另一個條目,如果您使用索引器。 (它不會,如果您使用Add方法 - 它會拋出一個異常,而不是

基本上我們猜測,直到我們看到一些代碼,或者至少得到更多的情況下,雖然...

+0

謝謝喬恩。我已經添加了更新的詳細情況和問題。如果您有任何意見,請發表評論。你的想法是真的很少,如果不是不可能的話,那麼我的Dictionary對象會「默默地丟失數據」?因爲該程序沒有以任何方式崩潰。 – tete 2012-07-07 20:24:12

+0

@tete:不,如果這是'Dictionary'中的問題,我會感到驚訝。在您的代碼中某處出現問題的可能性更大。 – 2012-07-08 06:44:58

2

聽起來像一個。 。祕方競爭條件

你可能有一些代碼,看起來像這樣:

if (!myDictionary.ContainsKey(key)) 
{ 
    //point of interest 
    myDictionary[key] = new Dictionary<X, Y>() 
} 
myDictionary[key][innerkey] = innnervalue; 

的問題是,兩個線程使其利息評論來看,有條件內你不真的打算爲s運行該塊兩次但是,線程魔法會讓它發生。

  1. 線程A和線程B使其成爲興趣點。
  2. 線程A喚醒並運行該方法的其餘部分。
  3. 線程B被喚醒並運行,成爲孤兒線程A創建的字典

您可以通過保護共享實例上鎖後面解決這個問題:

lock(_theLockInstance) 
{ 
    if (!myDictionary.ContainsKey(key)) 
    { 
    //point of interest 
    myDictionary[key] = new Dictionary<X, Y>() 
    } 
    myDictionary[key][innerkey] = innnervalue; 
} 

現在,只有一個線程可以一次到達關鍵部分,不會創建孤兒字典。

+0

謝謝大衛。我確實意識到了多線程問題,並且已經爲Dictionary的每個操作添加了一個鎖。 (請看我的更新) – tete 2012-07-07 20:26:59