使用模板创建ConcurrentBag

时间:2016-05-11 20:17:31

标签: c# multithreading thread-safety

编写以下代码是为了创建由列表组成的数组池。我想稍后在并行foreach中使用它。要创建池,我想通过预先填充的模板进行复制。

List<candle>[] sourceCandleList = new List<candle>[3];
// populate sourceCandleList here with data
ConcurrentBag<List<candle>[]> poolList = new ConcurrentBag<List<candle>[]>();
int maxThreads = 64;
for (int i = 0; i < maxThreads; i++)
{
    poolList.Add(sourceCandleList);
}

这会创建64个sourceCandleList的深层副本吗?如果没有,ConcurrentBag仍然是线程安全的吗? 我之所以不确定,是因为如果我清除sourceCandleList之类的sourceCandleList.Clear(),那么ConcurrentBag中的所有列表都会显示为空。

2 个答案:

答案 0 :(得分:1)

ConcurrentBag本身仍然是线程安全的,但是这段代码最终只是添加了64个指针,这些指针都引用了相同的List对象数组。它添加了64次相同的数组,因此对一个数组所做的任何更改都将发生在所有数组中。

您需要手动制作每个数组的深层副本,每个数组中的每个列表,以及可能每个蜡烛(如果它是一个类,而不是一个不可变的结构)。它最终看起来像是:

for (int i = 0; i < maxThreads; i++)
{
    List<candle>[] candleList = new List<candle>[3];
    for (int j = 0; j < 3; j++)
    {
        candleList[j] = new List<candle();
        foreach (candle c in sourceCandleList[j])
            candleList[j].Add(new candle(c.field1,c.field2)); // If it's an immutable struct, you should be able to just .Add(c)
    }
    poolList.Add(candleList);
}

您可能会使用LINQ来实现这一点,但我不确定您正在运行哪个版本的.NET。

答案 1 :(得分:0)

@zfrank 对不起,我无法将此作为评论发布 下面是否也会创建一个深层复制的技巧?在我的理解中,ConvertAll创建了一个深层副本。

for (int i = 0; i < maxThreads; i++)
     {
      List < candle >[] CandleList = new List<candle>[sourceCount];
      for (int w = 0; w <= sourceCount - 1; w++)
           {
                CandleList[w] = sourceCandleList[w].ConvertAll(c => c);
           }
           poolList.Add(CandleList);
      }
相关问题