Reputation: 359
I have this code, where I am trying to update item(which is a list) in my concurrent dictionary for a key (key is same all the time).
Here is my code -:
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;
}
});
}
}
one out of 10 times above code is throwing exception - "Source array was not long enough. Check srcIndex and length, and the array's lower bounds."
I know this is a synchronization issue of list , but I am not getting why is this coming , since ConcurrentDictionary is thread safe. so I assume, it lets only one thread to update my list at one time, so there should not be any problem-:
I know I am missing something - suggestions please -:
Upvotes: 0
Views: 374
Reputation: 178
ConcurrentDictionary can be thread-safe, but List is not.
Look at decompiled method from List:
public void Add(T item)
{
if (this._size == this._items.Length)
this.EnsureCapacity(this._size + 1);
this._items[this._size++] = item;
++this._version;
}
Thread #1 and Thead #2 can pass if (this._size == this._items.Length)
at the same time. Thread #1 will set value here this._items[this._size++] = item;
, but Thread #2 will cause IndexOutOfRangeException. You need thread-safe list.
update You can use SynchronizedCollection instead of List
Upvotes: 4