让我们说我们有两个线程在运行,第一个是枚举列表,比如
foreach(int a in someList)
{
//Do something
//Thread 2 comes in
}
然后线程2将新实例分配给“someList”
someList = new List<int>();
问题1:thread1会发生什么?它会抛出异常还是继续枚举旧实例?答案 0 :(得分:1)
Foreach在GetEnumerator
上调用someList
,从而获得IEnumerator
类型的对象。此对象会记住原始列表,并逐个从中读取元素。
如果你现在为someList
分配新东西,那么:
break
s),IEnumerator仍会记住旧列表并从中读取证明:
using System;
using System.Collections.Generic;
static void Main()
{
var list = new List<int>{ 1,2,3,4,5};
foreach(var x in list) // foreach grabs old list and keeps it
{
Console.WriteLine(x);
list = new List<int>{9,9,9}; // replace the whole list
}
}
输出:
1
2
3
4
5
以上示例是单线程的,其行为与描述的相似。将其更改为多线程不会使事情变得更糟,因为foreach读取变量并记住实例一次,因此在多线程设计中,即使您没有添加锁并离开比赛,在最坏的情况下要么抓住旧列表,要么抓住新列表,但绝不会同时使用。
答案 1 :(得分:0)
问题1:如果我的记忆正常,它会引发异常。
问题2:也许,但这无关紧要,因为无论如何都应抛出异常。
如果您正在修改列表,上面的内容似乎是正确的,我的不好。