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

Dan*_*han 11 .net c# 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[];
}
Run Code Online (Sandbox Code Playgroud)

您可以推断,代码基本上是为网页上的下拉列表缓存一些值.

首先,它尝试从缓存中读取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)
Run Code Online (Sandbox Code Playgroud)

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

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

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

Dar*_*rov 21

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