奇怪的“枚举器实例化后修改了集合”。例外 [英] Strange "Collection was modified after the enumerator was instantiated" exception

查看:173
本文介绍了奇怪的“枚举器实例化后修改了集合”。例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许有人可以指出正确的方向,因为我对此完全感到困惑。

Perhaps someone can point me in the correct direction, because I'm completely stumped on this.

我有一个函数可以简单地打印出类的LinkedList:

I have a function that simply prints out a LinkedList of classes:

    LinkedList<Component> components = new LinkedList<Component>();
    ...
    private void PrintComponentList()
    {
        Console.WriteLine("---Component List: " + components.Count + " entries---");
        foreach (Component c in components)
        {
            Console.WriteLine(c);
        }
        Console.WriteLine("------");
    }

Component 对象实际上有这样的自定义 ToString()调用:

The Component object actually has a custom ToString() call as such:

    int Id;
    ...
    public override String ToString()
    {
        return GetType() + ": " + Id;
    }

此功能通常可以正常工作-但是我遇到了一个问题,即它在列表中建立了约30个条目, PrintcomplentList foreach 语句返回一个 InvalidOperationException:枚举器实例化后修改了集合。

This function typically works fine - however I've run into the issue that when it builds to about 30 or so entries in the list, the PrintcomplentList foreach statement comes back with an InvalidOperationException: Collection was modified after the enumerator was instantiated.

现在,您可以看到我没有在for中修改代码循环,尽管这是在XNA环境中(如果有的话),但我没有明确创建任何线程。应该注意的是,打印输出的频率足够高,以至于控制台输出会减慢整个程序的速度。

Now as you can see I'm not modifying the code within the for loop, and I haven't explicitly created any threads, although this is within an XNA environment (if it matters). It should be noted that the printout is frequent enough that the Console output is slowing down the program as a whole.

我完全感到困惑,是否还有其他人在运行

I'm completely stumped, has anyone else out there run into this?

推荐答案

我怀疑开始查找的位置将在您操作列表的任何位置-即插入/删除/重新分配项目。我的怀疑是,某个地方将有一个异步触发的回调/偶数处理程序(也许是XNA paint 等循环的一部分),并且正在编辑列表-本质上导致此问题

I suspect the place to start looking will be at any places where you manipulate the list - i.e. insert/remove/re-assign items. My suspicion is that there will be a callback/even-handler somewhere that is getting fired asynchronously (perhaps as part of the XNA paint etc loops), and which is editing the list - essentially causing this problem as a race condition.

要检查是否存在这种情况,请将一些调试/跟踪输出放在操纵列表的位置周围,并查看是否曾经(尤其是) ,就在例外之前)在控制台输出的同时运行操作代码:

To check if this is the case, put some debug/trace output around the places that manipulate the list, and see if it ever (and in particular, just before the exception) runs the manipulation code at the same time as your console output:

private void SomeCallback()
{
   Console.WriteLine("---Adding foo"); // temp investigation code; remove
   components.AddLast(foo);
   Console.WriteLine("---Added foo"); // temp investigation code; remove
}

不幸的是,这种事情通常很难调试,因为更改代码进行调查通常可以解决问题( Heisenbug )。

Unfortunately, such things are often a pain to debug, as changing the code to investigate it often changes the problem (a Heisenbug).

一个答案是同步访问;例如,在 all 编辑列表的地方,在整个操作周围使用

One answer would be to synchronize access; i.e. in all the places that edit the list, use a lock around the complete operation:

LinkedList<Component> components = new LinkedList<Component>();
readonly object syncLock = new object();
...
private void PrintComponentList()
{
    lock(syncLock)
    { // take lock before first use (.Count), covering the foreach
        Console.WriteLine("---Component List: " + components.Count
              + " entries---");
        foreach (Component c in components)
        {
           Console.WriteLine(c);
        }
        Console.WriteLine("------");
    } // release lock
}

并在回调中(或其他方式) )

and in your callback (or whatever)

private void SomeCallback()
{
   lock(syncLock)
   {
       components.AddLast(foo);
   }
}

特别是,完整操作可能包括:

In particular, a "complete operation" might include:


  • 检查计数 foreach / 用于

  • 检查是否存在插入/删除


  • check the count and foreach/for
  • check for existance and insert/remove
  • etc

(即不是个人/离散操作,而是工作单位)

(i.e. not the individual/discrete operations - but units of work)

这篇关于奇怪的“枚举器实例化后修改了集合”。例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆