如何在C#中创建线程安全的列表池?

时间:2016-05-09 19:48:54

标签: c# multithreading

旧标题:C#中的列表数组线程是否安全? 我尝试使用列表池进行并行处理。我在数组中创建列表,然后使用ConcurrentBag的整数将它们分配给线程。由于整个代码很长,我做了一个摘录。在下面的示例中,每个线程都需要5个对象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);
});

所以这样运行没有错误或任何警告。但是在并行处理中,它有时无法更新ABCList [slot,1 .... 5]中的值。有时我的意思是1000个中的2-5个。当我检查调试模式时,我无法重现症状。当我按F11时,列表值会更新 请考虑我是一个业余爱好程序员,我可能会做一些明显错误的事情。任何想法如何正确地做到这一点?
修改
基于彼得的建议,我改写如下:

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);
});

问题仍然存在。在某些情况下,列表无法更新。我做错了什么?

1 个答案:

答案 0 :(得分:0)

您可以为线程安全集合使用System.Collections.Concurrent名称空间, and you can Use ConcurrentBag Class to Create Object(List) Pool

如果你想要池中的任何列表是线程安全的,你可以用户

var threadSafeArrayList = ArrayList.Synchronized(new ArrayList());

用于创建每个列表对象