请检查以下代码:
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
是一个线程安全的静态对象,但我无法想到导致该错误的任何其他内容。你们能帮助我找出原因吗?
答案 0 :(得分:21)
HttpContext.Current.Cache
对象本身是线程安全的,这意味着存储和读取它是线程安全的,但显然您存储在其中的对象可能不是线程安全的。在您的情况下,您存储的Hashtable
不是线程安全对象,这意味着此实例可能在多个线程之间共享,并且可能会对哈希表进行并发读取和写入,这可能会导致问题。