是否有可能将循环长度增加的循环并行化?
List<int> list = new List<int>() { 0, 1 };
for (int i = 0; i < list.Count; i++)
//Parallel.For(0, list.Count, (i) =>
{
Console.WriteLine(list[i]);
if (i == 0) list.Add(2);
}//);
//foreach (int i in list)
//Parallel.ForEach(list, (i) =>
//{
// Console.WriteLine(i);
// if (i == 0) list.Add(2);
//}//);
Console.ReadLine();
在这个简单的例子中,预期的输出是:
0
1
2
上面的代码可以正常使用序列号&#39; for&#39;但是对于序列号#fore;&#39;由于集合被修改。对于两个并行化的实现,代码完成但输出缺少最终的&#39;
。答案 0 :(得分:3)
更改for循环中的集合无效。基本上以任何方式修改列表会使枚举器无效。以下是IEnumerator文档的引用:
只要集合保持不变,枚举器仍然有效。如果对集合进行了更改,例如添加,修改或删除元素,则枚举数将无法恢复,并且其行为未定义。
有关详细信息,请查看this post。就并行实现而言:
Parallel.ForEach
- 这符合相同的IEnumerator问题,每个问题的标准都是Parallel.For
- 这将循环次数作为常量传递给for,而不是作为参考。这意味着当计数发生变化时,它不会改变它循环的次数更安全的模式是在调用parallels实现之前添加,删除和修改列表元素。然后线程可以处理这些元素。如果无法做到这一点,那么确定循环后您将拥有的元素数,然后使用数组按索引存储/处理这些元素。最后将任何非空值拉回到列表中。这样您就不必担心列表的线程安全问题(Insert
会推动其他元素前进,使您的索引无效)。以下应该有效:
// EX: might be initialized with a call to the database: "COUNT(id)"
int expectedElements = 10;
if (myList.Count < expectedElements)
for (var idx = myList.Count; idx <= expectedElements; idx++) myList.Add(null);
var elements = myList.ToArray();
System.Threading.Tasks.Parallel.For(0, expectedElements, (idx) =>
{
// "remove" the element
if (idx % 3 == 0) elements[idx] = null;
// "modify" the element
if (idx % 3 == 1) elements[idx] = DifferentElement(idx);
// "add" an element
if (idx % 3 == 2) elements[idx] = GetNewElement(idx);
});
// clear current list, add new elements, remove null values
myList.Clear();
myList.AddRange(elements);
myList.RemoveAll(item => item == null);
现在您可以根据需要“添加”,“删除”和“修改”,结果会回到列表中!
答案 1 :(得分:0)
for (int i = 0; i < list.Count; i++) //list.Count will only checked at first call
{
Console.WriteLine(list[i]);
if (i == 0) list.Add(2);
}
听起来像你的list.Count会被问到一个,然后它将被保存在内存中,在你的情况下,list.Count将是2并且永远不会移动,所以你将打印list [0]然后列出[1]。
您可能也对锁定感兴趣:
主题A:
lock (list) {
foreach (Object obj in list) {
obj.doSomething();
if(meet_condition) list2.add(obj)
}
}
其中list2是静态属性。
主题B:
lock (list) {
list.Remove(Element);
}
一旦线程锁定列表,其他线程一直等到它被释放才能使用它。 在不知道你试图用它做什么的情况下,很难帮助你。