我有这个代码,我试图在我的并发字典中更新项目(这是一个列表)的密钥(密钥始终相同)。
这是我的代码 - :
class Program
{
private static readonly ConcurrentDictionary<string, List<int>> s_mapDatatypeToSource = new ConcurrentDictionary<string, List<int>>();
static void Main(string[] args)
{
try
{
Parallel.For(0, 10000000, i => AddItemToList(i, "local"));
}
catch (Exception exception)
{
Console.WriteLine(string.Format("Exception thrown ...{0}", exception.Message));
Console.ReadLine();
throw;
}
Console.WriteLine("Completed without exception");
Console.ReadLine();
}
private static void AddItemToList(int dataKey, string sourceName)
{
s_mapDatatypeToSource.AddOrUpdate(sourceName.ToUpperInvariant(), new List<int> { dataKey }, (s, list) =>
{
{
list.Add(dataKey);
return list;
}
});
}
}
代码中有十分之一的代码抛出异常 - “源数组不够长。检查srcIndex和长度,以及数组的下限。”
我知道这是list的同步问题,但我不明白为什么会这样,因为ConcurrentDictionary是线程安全的。所以我假设,它只允许一个线程一次更新我的列表,所以应该没有任何问题 - :
我知道我遗失了一些东西 - 建议请 - :
答案 0 :(得分:4)
ConcurrentDictionary可以是线程安全的,但List不是。
从List中看反编译方法:
public void Add(T item)
{
if (this._size == this._items.Length)
this.EnsureCapacity(this._size + 1);
this._items[this._size++] = item;
++this._version;
}
线程#1和Thead#2可以同时传递if (this._size == this._items.Length)
。线程#1将在此设置值this._items[this._size++] = item;
,但线程#2将导致IndexOutOfRangeException。你需要线程安全列表。
更新您可以使用SynchronizedCollection代替列表