2011-11-09 12 views
4

我看到一個隨機異常「集合被修改;枚舉可能不會執行」 - InvalidOperationException。私有成員變量是否真的在類後面的asp.net代碼中線程安全?

異常指向下面的代碼片段中的foreach行,我知道這發生在枚舉時修改集合。

但是在我的情況下,我沒有看到它發生的真正機會 - 除非私有成員不是線程安全的..我可能是錯誤的,但在這裏我需要幫助理解並計算出

這裏是我的代碼看起來

我有隱藏類代碼其中有一個私人收藏一樣

private Dictionary<string, string> _someDictionary = SomeConstantClass.ConstantValue; 

在頁面預渲染完整的情況下,我列舉的詞典

protected override void OnPagePreRenderComplete(object sender, EventArgs e){ 
    _someDictionary["AnotherKey"] = "Another value"; 

    foreach(var dataValuePair in _SomeDictionary){ 
     //Do some operation 
    } 
} 

我也有一個公共財產可以修改這個集合,但它設置在ascx文件中,如

<tc: UserControlA runat="server" id="abc" CustomProperty="true" /> 

,這裏是它的實現,

public bool CustomProperty{ 
    set{ 
     if (value) 
      _someDictionary["CustomProperty"] = "Custom Value"; 
    } 
} 

這當然修改我的成員變量集 - 但按我的理解,這個屬性應該被解僱,並在控制初始化自身完成。

所以,我仍然沒有看到預渲染完成事件期間集合被修改的場景。

任何想法可能導致異常發生?

其他說明:該頁面當然有許多更新面板,雖然這個特定的用戶控件沒有做任何花哨的事情,甚至沒有回發場景。 從日誌中我發現問題發生在對頁面的HTTP GET請求中。

此外:建議我一種方法(如果有的話)來重現這一點。

對於我的朋友誰是興趣知道SomeConstantClass.ConstantValue,這裏是

class SomeConstantClass{ 
    public static Dictionary<string, string> ConstantValue = new Dictionary<string, string> { 
         {"ABCD", "EFGH"}, 
         {"HIJK", "LMNO"} 
        }; 
    } 
+2

什麼是SomeConstantClass.ConstantValue?這是靜態的嗎? –

+0

有趣的是,你忽略了在我們看起來的第一個地方內執行的實際代碼。 –

+0

@AnonyPegram你有興趣知道什麼是在foreach循環內? – humblelistener

回答

7

如果從SomeConstantClass.ConstantValue那麼多頁返回相同的情況下將有私有成員變量指向同一個對象。這將導致該對象在一個頁面的初始化過程中被更改,而在另一個頁面的OnPagePreRenderComplete上迭代該對象。

請確保您在每次訪問SomeConstantClass.ConstantValue時都返回字典的新實例。例如:

public static Dictionary<string, string> ConstantValue 
{ 
    get 
    { 
     return new Dictionary<string, string> 
     { 
      {"ABCD", "EFGH"}, 
      {"HIJK", "LMNO"} 
     }; 
    } 
} 

這樣每個頁面都會有它自己的字典對象來處理。這是快速的解決方案,您可以重構邏輯,以便您不必爲每個頁面創建新的字典。

基本上私有成員變量只有在它們引用一個對該頁面是私有的對象並且沒有其他人知道該對象或該對象本身被設計爲線程安全的情況下才是線程安全的。通過私有成員封裝對非線程安全的靜態對象的訪問不會使其線程安全。

+1

通過私有成員封裝對非線程安全的靜態對象的訪問不會使其線程安全。 - 我沒有意識到這一點..謝謝。 – humblelistener

2

只要你知道你沒有跨請求共享字典(或者你故意這樣做),你可以跳過試圖找出原因,並使用線程安全的Concurrent Dictionary。僅僅因爲字典是私人的並不能保證它的線程安全。

+0

-1使用併發字典並在所有頁面中共享將意味着用戶控件上的'CustomProperty =「true」'是毫無意義的,因爲頁面添加到字典中的任何項目對其他頁面也是可見的。 –

相關問題