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

我的功能只能打印出链接列表的类:

    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() 这样致电:

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

此功能通常可以正常工作 - 但是,我遇到了一个问题,即当它构建到列表中约30个条目时, PrintcomplentList foreach 陈述带有一个 InvalidOperationException: Collection was modified after the enumerator was instantiated.

现在,如您所见,我没有在for循环中修改代码,但我没有明确创建任何线程,尽管这在XNA环境中(如果很重要)。应该注意的是,打印输出很频繁,因此控制台输出正在减慢整个程序。

我完全很困难,还有其他人遇到过吗?

有帮助吗?

解决方案

我怀疑可以在您操纵列表的任何地方开始寻找的地方 - 即插入/删除/重新分配项目。我的怀疑是,在某个地方会有一个回调/均匀的手机,该回调异步被射击(也许是XNA的一部分 ETC循环),并且正在编辑列表 - 本质上是导致此问题作为种族条件。

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

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

不幸的是,这样的事情通常是一个痛苦的调试,因为更改代码进行调查通常会改变问题(一个 海森伯格).

一个答案是同步访问;即IN 全部 编辑列表的地方,使用 lock 围绕完整的操作:

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
}

在您的回调(或其他)中

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

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

  • 检查计数 foreach/for
  • 检查存在 插入/删除
  • ETC

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

其他提示

代替 foreach, , 我用 while( collection.count >0) 然后使用 collection[i].

我不知道这是否与OP有关,但是我遇到了相同的错误,并在Google搜索过程中找到了此线程。我能够通过在循环中删除元素后添加休息来解决它。

foreach( Weapon activeWeapon in activeWeapons ){

            if (activeWeapon.position.Z < activeWeapon.range)
            {
                activeWeapons.Remove(activeWeapon);
                break; // Fixes error
            }
            else
            {
                activeWeapon.position += activeWeapon.velocity;
            }
        }
    }

如果您忽略了休息时间,您将获得错误“ InvalidOperationException:在实例化枚举后进行了修改。”

使用 Break 可能是一种方式,但可能会影响您的一系列操作。在这种情况下,我只需转换 foreach 传统 for 环形

for(i=0; i < List.count; i++)
{
    List.Remove();
    i--;
}

这无问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top