编写以下代码是为了创建由列表组成的数组池。我想稍后在并行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中的所有列表都会显示为空。
答案 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);
}