【发布时间】:2011-07-07 13:48:24
【问题描述】:
我们有一个非常严重的问题,每分钟会导致数千个异常。我们有一个网站,它运行一种本地缓存机制,以以下形式保存数据:
protected static IDictionary<int, IList<IInterfaceForData>> m_Data = null;
当我们在这个字典上调用 Add 时,我们得到一个非常奇怪的行为:“Index was outside the bounds of the array”,当键 100% 不在字典中时: p>
m_Data.Add(id, new List<IInterfaceForData>());
我们使用这样的锁来保护这个调用:
if(Monitor.TryEnter(m_LockObj, 1000))
{
try
{
m_Data.Add(id, new List<IInterfaceForData>());
}
catch(Exception ex)
{
// log exception
}
finally
{
Monitor.Exit(m_LockObj);
}
}
我们得到了这个异常:
at System.Collections.Generic.Dictionary`2.Resize() at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
我们找不到任何解释,因为异常与 Dictionary 的线程安全有关,而我们(认为我们)是线程安全的。我们在每个 Add() 和 Remove() 调用上使用 lock() 或 Monitor.TryEnter,除了 m_Data.TryGetValue(...)
任何帮助将不胜感激。
非常感谢。
【问题讨论】:
-
您也必须锁定
TryGetValue,以及读取或更新字典的任何其他内容。TryGetValue往往会在其他线程同时添加或删除项目时表现出不可预测的行为。 -
也许您将 generic 字典中的
TryGetValue与 concurrent 字典中的TryGetValue混淆了,因为它们都是最近才引入的( .NET 3.5 和 .NET 4)。 -
@贾斯汀:什么?
Dictionary<TKey, TValue>.TryGetValue一直存在! -
@DanTao - 哎呀,我猜我只是被msdn.microsoft.com/en-us/library/bb347013.aspx上的“其他版本”下拉菜单弄糊涂了
-
@Jim,锁定 TryGetValue 会将代码更改为 Single Reader,我希望它是 MultiReader。
标签: .net dictionary c#-3.0 thread-safety