Reputation: 829
Old title: Is an array of lists thread safe in C#?
I try to use a pool of lists for parallel processing. I create lists in an array and then use a ConcurrentBag of integers to allocate them to threads. Since the entire code is quite long I made an excerpt. In the below example each thread would need 5 lists of object x.
int maxThreads = 64;
ConcurrentBag<int> pool = new ConcurrentBag<int>();
// Populate ConcurrentBag with values 0 through 63
for (int i = 0; i <= maxThreads - 1; i++)
{
pool.Add(i);
}
List<x>[,] ABCList = new List<x>[maxThreads, 5];
Parallel.ForEach(zList,
new ParallelOptions { MaxDegreeOfParallelism = maxThreads },
p =>
{
while (!pool.TryTake(out slot));
// Do something here with ABCList[slot, 1....5]
// Example: ABCList[slot, 1].[1].Field1 = 2;
// Example: ABCList[slot, 1].[1].Field2 = "abc";
pool.Add(slot);
});
So this runs without an error or any warnings. However inside parallel processing it sometimes fails to update values in ABCList[slot, 1....5]. By sometimes I mean 2-5 cases out of 1000. When I check in debug mode I can't reproduce the symptom. When I press F11 the list values are updated.
Please consider that I'm a hobby programmer and I may do something obviously wrong here. Any ideas how to do this correctly?
EDIT
Based on the suggestion of Peter I rewrote like this:
int maxThreads = 64;
ConcurrentBag<int> pool = new ConcurrentBag<int>();
ConcurrentDictionary <int, List<x>[]> ABCList = new ConcurrentDictionary<int, List<x>[]>();
// Initialize ConcurrentDictionary
for (int i = 0; i < maxThreads; i++)
{
pool.Add(i);
ABCList[i] = new List<x>[5];
for (int w = 0; w <= 4; w++)
{
ABCList[i][w] = templateABCList[w].ConvertAll(p => p);
}
}
Parallel.ForEach(zList,
new ParallelOptions { MaxDegreeOfParallelism = maxThreads },
p =>
{
while (!pool.TryTake(out slot));
// Do something here with ABCList[slot][1...5]
// Example: ABCList[slot][1][1].Field1 = 2;
// Example: ABCList[slot][1][1].Field2 = "abc";
pool.Add(slot);
});
The problem still exists. The list fails to update in some cases. What do I do wrong?
Upvotes: 0
Views: 585
Reputation: 381
You can Use System.Collections.Concurrent Name Space for Thread Safe Collections, and you can Use ConcurrentBag Class to Create Object(List) Pool
if you want Any list in pool is Thread safe , you can Use
var threadSafeArrayList = ArrayList.Synchronized(new ArrayList());
For Create each List Object
Upvotes: 0