【问题标题】:Collection was modified; enumeration operation may not execute." Collection elements are not modified收藏已修改;枚举操作可能无法执行。” 集合元素未修改
【发布时间】:2011-03-31 09:05:33
【问题描述】:

我的代码中有一个嵌套循环“结构”。有时,我会收到以下消息。

集合已修改;枚举操作可能无法执行。

我有一个正在循环浏览的集合,如下所示。 Coll 是 List<string>

foreach (string[] s1 in obj.Coll
{
    foreach (string s in s1) { }
}

对于数组中的每个字符串,我需要使用它(读取为读取值,而不是写入)。 我所做的只是获取目录(这个值是一个路径)并将这个字符串拆分成一个数组。

如何解决?

【问题讨论】:

标签: c#


【解决方案1】:

obj.Coll 在您枚举时已更改。如果它没有被当前线程改变,它可能被其他线程改变。如果当前线程更改了集合,基本上有两种方法可以解决问题:可以创建集合的副本并枚举副本,也可以推迟更改直到枚举集合。

但是,如果集合被另一个线程更改,您应该以线程安全的方式访问该集合(不仅仅是这里,而是无处不在)。

编辑 基伦·约翰斯通:

我写了一个简短的代码来证明List<T>.ToArray() 不是线程安全的。

var list = new List<int>();

Task.Factory.StartNew(() => {
    for (int i = 0; i < 1000000; ++i) {
        list.Clear();

        // Add values from 1 to 9
        for (int j = 1; j < 10; ++j) {
            list.Add(j);
        }
    }

    Console.WriteLine("Thread Exit: list.Add()");
});

Task.Factory.StartNew(() => {
    for (int i = 0; i < 100; ++i) {
        var array = list.ToArray();
        if (array.Length > 0) {
            Console.WriteLine("ToArray(): {0}", string.Join(", ", array));
        }
    }

    Console.WriteLine("Thread Exit: list.ToArray()");
});

下面是输出的sn-p。我想这证明了我的主张。 sn-p 包含 15 行,其中 9 行包含错误数据。

ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 6, 7, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 0, 0, 0, 4, 5, 6, 7
ToArray(): 1, 2, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3
ToArray(): 1, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2
ToArray(): 1, 2, 3
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 6, 7, 8

如果我们使用list.Insert(0, j) 而不是list.Add(j),将会有更多变化。

【讨论】:

    【解决方案2】:

    你可以试试:

    foreach (string[] s1 in obj.Coll.ToArray())
    {
    

    这将在开始迭代之前进行复制!

    【讨论】:

    • 请注意,这仅在集合未被另一个线程更改时才有效,因为ToArray() 不是线程安全的。
    • 我多年来一直在重负载的多线程应用程序中使用它,没有一个错误或问题,你确定吗?
    • 嗯,你是对的。看起来我什至自己发现了这一点并忘记了 - 我在该代码周围有锁和事件:)
    猜你喜欢
    • 2012-04-01
    相关资源
    最近更新 更多