2012-12-05 10 views
6

Mentre sto lavorando sul parallelismo del nostro framework, ho affrontato una strana condizione che non riesco a immaginare perché! Ho semplificato la situazione per descriverla facilmente. considerare questo codice:Modifica di una variabile locale su null, tramite un altro thread, com'è possibile

foreach(var person in personList) 
{ 
    if (person.Name == "Mehran") 
     break; 
} 

cui il personList è condiviso tra più thread.

In quali circostanze è possibile per person di essere null e ho la NullReferenceException per person.Name?

Per quanto ne so, la persona è considerata come una variabile locale qui e se la si riesce a mettere il blocco foreach, quindi abbiamo reiterato la personList con successo, in modo da person non dovrebbe essere nulla in nessun caso o qualsiasi scenario parallelo.

Anche se lo personList viene modificato da un altro thread o il riferimento person viene eliminato, la variabile person deve avere un valore. Perché nessuno ha accesso al cambiamento a cui si fa riferimento a person.

C'è qualche scenario per spiegare la situazione?

risposta

11

Per quanto ne so, la persona è considerata come una variabile locale qui e se la si riesce a mettere il blocco foreach, quindi abbiamo reiterato la personList con successo, in modo da persona non dovrebbe essere nulla in nessun caso o qualsiasi scenario parallelo .

Solo perché sei l'iterazione di personList successo non significa che non contiene valori nulli. Per esempio:

List<Person> personList = new List<Person>(); 
personList.Add(null); 

foreach (var person in personList) 
{ 
    // Here, person will be null 
} 

(Inoltre, se nulla sta modificando la lista, sei generalmente in difficoltà - non sono thread-safe a fronte di scrittori - ma non credo che le esigenze essere parte del problema.)

+0

Wooops! le liste possono accettare null! Situazioni parallele mi hanno fatto pensare più complicato del necessario! Grazie mille Jon. – mehrandvd

+0

Sì, conosco i problemi di modifica dell'elenco in situazioni parallele. Penso che la tua risposta semplice e veloce lo risolva. Controllerò per eventuali null nella lista. – mehrandvd

3

La variabile non viene modificata. L'iteratore utilizzato per attuare il foreach costrutto non è thread sicuro:

Dalla documentazione di List<T>.IEnumerable<T>.GetEnumerator() trovato here:

Un enumeratore rimane valido finché la raccolta rimane invariato. Se vengono apportate modifiche alla raccolta, come l'aggiunta, la modifica o l'eliminazione di elementi, l'enumeratore viene irrimediabilmente invalidato e il suo comportamento non è definito.

L'enumeratore non ha accesso esclusivo alla raccolta; pertanto, l'enumerazione tramite una raccolta non è intrinsecamente una procedura thread-safe. Per garantire la sicurezza dei thread durante l'enumerazione, è possibile bloccare la raccolta durante l'intera enumerazione. Per consentire l'accesso alla raccolta da più thread per la lettura e la scrittura, è necessario implementare la propria sincronizzazione.

Le implementazioni predefinite di raccolte nello spazio dei nomi System.Collections.Generic non sono sincronizzate.

Si dovrebbe sempre bloccare gli elenchi mentre si itera su di essi se esiste la possibilità che un altro thread possa modificare l'elenco.

Problemi correlati