2011-01-27 135 views
10

請檢查下面的代碼:HttpContext.Current.Cache線程安全嗎?

objDDLTable = HttpContext.Current.Cache["TestSet"] as Hashtable; 

if (objDDLTable == null) 
{ 
    objDDLTable = new Hashtable(); 
    arrDDLItems = GetDropDownList("testDropDown"); 
    objDDLTable.Add("testDropDown", arrDDLItems); 
    HttpContext.Current.Cache["TestSet"] = objDDLTable; 
} 
else if (objDDLTable != null && !objDDLTable.Contains("testDropDown")) 
{ 
    arrDDLItems = GetDropDownList("testDropDown"); 
    objDDLTable.Add("testDropDown", arrDDLItems); 
    HttpContext.Current.Cache["TestSet"] = objDDLTable; 
} 
else 
{ 
    arrDDLItems = objDDLTable["testDropDown"] as DdlItem[]; 
} 

的代碼,你可以推斷出,基本上是緩存一些值在網頁上的下拉列表。首先,它試圖從緩存中讀取HashTable對象,然後檢查從緩存讀取的HashTable對象中是否存在特定的鍵。如果是這樣,則讀取值(項目數組),否則從源讀取數組,然後在HashTable中添加一個新密鑰,然後將其存儲回高速緩存以供後續使用。

這在大多數情況下正常,但是,我們已經得到了以下錯誤偶爾:

System.ArgumentException: Item has already been added. 
Key in dictionary: 'testDropDown' Key being added: 'testDropDown' at 
System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at 
System.Collections.Hashtable.Add(Object key, Object value) 

從邏輯上講,應該永遠當系統嘗試添加的關鍵testDropDown在哈希表時的情況下,它已經存在,第一個條件不應該允許它。

唯一讓我想到的是另一個線程在第一個線程上條件檢查失敗時向HashTable添加鍵的可能性,並且它還試圖添加鍵。

據我所知,Cache是一個線程安全的靜態對象,但我想不出任何其他導致該錯誤的東西。你們能幫我找出原因嗎?

回答

20

HttpContext.Current.Cache對象本身是線程安全的,這意味着存儲和讀取它是線程安全的,但很明顯,您存儲在內部的對象可能不是線程安全的。在你的情況下,你正在存儲一個不是線程安全對象的Hashtable,這意味着這個實例可能會在多個線程之間共享,並且可能會同時讀取和寫入散列表,這可能會導致問題。

+1

具體而言,在這種情況下,您添加的Hashtable不是線程安全的,但更重要的是,多個線程可以同時訪問中間塊。 – 2011-01-27 16:08:14