Domanda

Sto cercando un modo per ottenere una raccolta simultanea in C# o almeno una raccolta che supporti un enumeratore simultaneo.In questo momento ricevo un'eccezione InvalidOperationException quando la raccolta su cui sto eseguendo l'iterazione cambia.Potrei semplicemente copiare in profondità la raccolta e lavorare con una copia privata, ma mi chiedo se forse esiste un modo migliore

Frammento di codice:

foreach (String s in (List<String> )callingForm.Invoke(callingForm.delegateGetKillStrings))
    {
        //do some jazz
    }

--modificare--

Ho preso la risposta ma ho anche scoperto che dovevo assicurarmi che anche il codice che stava scrivendo nella raccolta dovesse tentare di ottenere un blocco.

    private void addKillString(String s)
    {
        lock (killStrings)
        {
            killStrings.Add(s);
        }
    }
È stato utile?

Soluzione

Oltre a eseguire una copia approfondita, la soluzione migliore potrebbe essere quella di bloccare la raccolta:

   List<string> theList = (List<String> )callingForm.Invoke(callingForm.delegateGetKillStrings);
    lock(theList.SyncRoot) {
        foreach(string s in theList) {
               // Do some Jazz
        }
    }

Altri suggerimenti

Quindi non sono del tutto sicuro di quello che stai chiedendo, ma il team di Parallel Extensions ha messo insieme alcune cose che potrebbero fare al caso tuo.Vedi questo post del blog in particolare, about enumerazione di collezioni parallele.Contiene anche un collegamento per scaricare Parallel CTP e ovviamente puoi sfogliare il resto dei post del blog per avere un'idea di cosa dovrebbe fare il CTP e di come funziona il modello di programmazione.

Se desideri utilizzare le raccolte FCL, il blocco è l'unico modo per supportare l'iterazione/modifica da più thread che potrebbero sovrapporsi.

Fai attenzione a cosa usi come oggetto di blocco, però.Usare SyncRoot è una buona idea solo se la raccolta stessa è un membro privato della classe che la utilizza.Se la raccolta è protetta o pubblica, un client della tua classe può bloccare il tuo SyncRoot, potenzialmente bloccandolo con il codice nella tua classe.

Se sei interessato a dare un'occhiata a una libreria di raccolte di terze parti, ti consiglio l'eccellente Libreria di raccolte generiche C5.Hanno una famiglia di raccolte basate su alberi che possono essere modificate e ripetute facilmente e in sicurezza allo stesso tempo senza blocchi - vedere le sezioni 8.10 e 9.11 della loro (eccellente) documentazione per i dettagli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top