下面的代码似乎有效 - 也就是说,使用增量整数的子列表填充外部List。
我只是幸运吗?
我小心翼翼地预先分配“插槽”而不是越过。
class Program
{
static List<List<int>> allLists;
static void Main(string[] args)
{
allLists = new List<List<int>>(553);
for (int i = 0; i < 553; i++)
{
allLists.Insert(i, new List<int>());
}
Enumerable.Range(0, 552).AsParallel().ForAll((i) => InsertRange(i));
}
static void InsertRange(int index)
{
allLists[index] = Enumerable.Range(0, 7205).ToList();
}
}
是否存在一个列表会破坏另一个列表的危险?
答案 0 :(得分:1)
是的,你应该锁定InsertRange方法。但要确保元素的创建仍然是并行完成的:
private static Object settingValue = new Object();
static void InsertRange(int index)
{
// This part can be executed in parallel.
List<int> values = Enumerable.Range(0, 7205).ToList();
lock (settingValue)
{
allLists[index] = values;
}
}
编辑:可能你很幸运,因为创建列表会花费相当多的时间来分配对索引号的引用,一个分配很可能与另一个完全重叠。
答案 1 :(得分:1)
并行访问数组的不同部分在.Net中是线程安全的。由于List<T>
由数组支持,我认为您的代码也应该是线程安全的。
但我认为你的事情过于复杂。您可以使用PLINQ生成所有内部列表,然后使用ToArray()
创建最终数组(或ToList()
,如果您确实要创建List<T>
)。由于PLINQ有自己的版本Range()
和ToArray()
(和ToList()
),我相信这也会更有效。
所以,我会像这样重写你的代码:
allLists = ParallelEnumerable.Range(0, 552)
.AsOrdered()
.Select(i => Enumerable.Range(0, 7205).ToList())
.ToArray();
当然,只有当并行创建内部列表实际上会加快代码速度时,这一切才有意义,但你必须自己衡量。
答案 2 :(得分:0)
根据Potential pitfalls with PLINQ,您可以使用潜在的非线程安全方法InsertRange(int index)