5

Ho un IEnumerable che voglio passare a Parallel.ForEach, ma l'IEnumerable è implementato usando un metodo C# e produce, e potenzialmente il codice nell'enumeratore è non thread sicuro. Stava pensando di usare Parallel.ForEach su questo. Sono sotto il presupposto che l'iterazione interna effettiva dell'IEnumerable di ForEach sia sempre sullo stesso thread, quindi ForEach passa ciascun elemento a un altro thread potenziale per l'elaborazione. È corretto?C# Parallel.ForEach utilizza lo stesso thread per le iterazioni della raccolta

Ho letto dove IEnumerable iteration utilizza l'archiviazione locale del thread e thread diversi che accedono allo stesso IEnumerable avranno ciascuno la propria iterazione corrente, successiva, ecc. Questo è il motivo per cui presumo che ForEach eseguirà effettivamente tutta l'iterazione sullo stesso filo.

Almeno so che l'iterazione non si trova sullo stesso thread chiamato Parallel.ForEach. Un pò sperando che fosse da quando ho bisogno di fare un'inizializzazione del thread per il thread che sta facendo l'iterazione. Quindi potrebbe esserci un problema qui per iniettare la mia inizializzazione sul thread facendo l'iterazione.

+0

presumo che non vogliate utilizzare il multithreading su qualcosa che non sia thread-safe. – DLeh

+0

Voglio che l'enumerazione sia thread-safe su un singolo thread, ma l'elaborazione effettiva dei singoli elementi può essere su più thread. – Ron

+0

Quindi, sembra dai commenti che sta iterando gli elementi nella stessa discussione. Ora, vorrei solo che lo facesse sul thread principale, o, credo, un modo per collegarlo. Cercherò di avvolgere un altro metodo con i rendimenti e vedere se riesco a inizializzare il thread prima di cedere ogni elemento – Ron

risposta

5

È impossibile scrivere un IEnumerator che può essere tranquillamente iterato da più thread. L'API è intrinsecamente contraria a consentire tale comportamento. Per questo motivo Parallel.ForEach non ha altra scelta se non quella di enumerare la sequenza da un singolo thread. Per esporre direttamente l'iteratore a ciascuno dei thread generati, è necessario utilizzare un'API diversa da quella che espone IEnumerator/IEnumerable.

+1

Non sono sicuro che sia esatto. È possibile enumerare in modo sicuro da diversi thread purché le chiamate MoveNext siano sincronizzate e ciò può facilmente interrompere qualsiasi cosa che dipende dall'archiviazione locale dei thread. – Stilgar

+3

@Stilgar No, non è possibile enumerare un enumeratore in modo sicuro da più thread. Prima di tutto, l'intero punto di farlo significherebbe che le chiamate a 'MoveNext' * non sarebbero * sincronizzate. Questo è ciò che significherebbe per loro essere progettati per essere enumerati in modo sicuro da più thread. Inoltre, non si può mai essere sicuri che il valore di "Current" sia effettivamente applicato alla mossa fatta dal thread; vedresti due thread spostare l'iteratore allo stesso tempo, e quindi entrambi usano il valore corrente della seconda mossa. – Servy

+0

Da quello che ho capito, se si esegue l'iterazione da più thread, ogni thread avrà ciascuno i propri passaggi di iterazione privati. per esempio. se 10 elementi nell'enumerazione, ogni thread eseguirà iterazione in modo indipendente attraverso ciascuno dei 10 elementi (anziché un thread ne ottiene alcuni, un altro thread ne ottiene alcuni, ecc.) – Ron