Tal vez alguien puede me apunte en la dirección correcta, porque estoy completamente confundido en esto.

Tengo una función que simplemente imprime un LinkedList de clases:

    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("------");
    }

La Component objeto tiene una costumbre de ToString() llamar como tal:

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

Esta función normalmente funciona bien – sin embargo, me he topado con el problema de que cuando se construye alrededor de un 30 o así que las entradas en la lista, el PrintcomplentList foreach declaración viene de vuelta con un InvalidOperationException: Collection was modified after the enumerator was instantiated.

Ahora, como usted puede ver, yo no estoy modificando el código dentro del bucle for, y yo no he creado explícitamente cualquier hilos, aunque esto está dentro de un XNA medio ambiente (si es importante). Cabe señalar que la impresión es bastante frecuente que la salida de la Consola es ralentizar el programa como un todo.

Estoy completamente perplejo, ha alguien más ahí fuera ejecutado en este?

Que suena muy extraño. Podría publicar un breve pero completa programa para que podamos intentar reproducirlo?
Voy a ver qué puedo hacer.
Yo cna no consigue un pequeño programa para replicar el comportamiento, así que voy a ver acerca de la introducción de un hilo de ejecución segura de LinkedList allí para ver si se prende nada

OriginalEl autor cyberconte | 2009-05-10

4 Comentarios

  1. 10

    Sospecho que el lugar para iniciar la búsqueda será en cualquier de los lugares donde se manipula la lista – es decir, insertar/quitar/re-asignar elementos. Mi sospecha es que habrá una devolución de llamada/aun-controlador en algún lugar que es ser despedido de forma asincrónica (tal vez como parte de XNA pintura etc bucles), y que es la edición de la lista – esencialmente causando este problema como una condición de carrera.

    Para comprobar si este es el caso, poner un poco de depuración/salida de la traza alrededor de los lugares que manipular la lista, y a ver si alguna vez (y, en particular, justo antes de la excepción) se ejecuta el código de la manipulación, al mismo tiempo que su salida de la consola:

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

    Por desgracia, las cosas son a menudo un dolor de depuración, como cambiar el código para investigar a menudo cambia el problema (un Heisenbug).

    Una respuesta sería para sincronizar el acceso; es decir, en todos los lugares que editar la lista, utilice un lock alrededor de toda la operación:

    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
    }

    y en su devolución de llamada (o lo que sea)

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

    En particular, una «completa la operación» podría incluir:

    • comprobar el recuento de y foreach/for
    • de verificación para la existencia y insertar/quitar
    • etc

    (es decir, no el individuo/operaciones discretas – pero las unidades de trabajo)

    tenga en cuenta también que la explotación del subproceso de identificación al momento de escribir su traza líneas pueden ayudar a identificar si hay competencia hilos, y por lo tanto la posibilidad de una carrera.

    OriginalEl autor Marc Gravell

  2. 4

    Lugar de foreach, yo uso while( collection.count >0), a continuación, utilizar collection[i].

    OriginalEl autor arash

  3. 2

    No sé si esto es relevante para el OP, pero yo tenía el mismo error y encontré este hilo durante una búsqueda en google. Yo era capaz de resolverlo mediante la adición de un descanso después de la eliminación de un elemento en el bucle.

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

    Si se deja fuera de la ruptura, obtendrá el mensaje de error «excepción InvalidOperationException: Colección fue modificado después de que el enumerador se crea una instancia.»

    Esto presenta otro error, aunque ninguna de sus armas en la lista después de que la primera fuera de la gama de armas no tienen sus puestos modificados! Me he ocupado de esto en el pasado mediante la creación de una segunda Lista de cosas a quitar de la primera lista, la etnogénesis en un foreach, a continuación, hacer un foreach sobre el segundo de la lista y la eliminación de cada elemento de la primera lista.

    OriginalEl autor Steffan

  4. 0

    Utilizando Break podría ser un camino, pero es posible el impacto en su serie de la operación.
    ¿Qué puedo hacer en ese caso, simplemente en convertir el foreach tradicional for bucle

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

    Esto funciona sin problemas.

    Que podría funcionar, pero en este caso, la iteración es sobre los objetos de una colección. foreach(var obj en la colección.teclas)…

    OriginalEl autor Saikat Chakraborty

Dejar respuesta

Please enter your comment!
Please enter your name here