2011-01-27 122 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