HttpContext.Current.Cache是​​否是线程安全的?

时间:2011-01-27 16:02:29

标签: c# .net caching

请检查以下代码:

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)

从逻辑上讲,当系统尝试在HashTable中已经存在时添加密钥testDropDown时,应该永远不会出现这种情况,第一个其他条件不应该允许它。

我唯一想到的是另一个线程的可能性,当第一个线程上的条件检查失败时,另一个线程将键添加到HashTable,并且它还尝试添加密钥。

据我所知,Cache是一个线程安全的静态对象,但我无法想到导致该错误的任何其他内容。你们能帮助我找出原因吗?

1 个答案:

答案 0 :(得分:21)

HttpContext.Current.Cache对象本身是线程安全的,这意味着存储和读取它是线程安全的,但显然您存储在其中的对象可能不是线程安全的。在您的情况下,您存储的Hashtable不是线程安全对象,这意味着此实例可能在多个线程之间共享,并且可能会对哈希表进行并发读取和写入,这可能会导致问题。