2012-06-01 16 views
7

Ho un problema ricorsivo in cui i consumatori lavorano un po 'a ogni livello di un albero, quindi devono recedere dall'albero e svolgere lo stesso lavoro al livello successivo.Come faccio a utilizzare una blockingcollection nel pattern Producer/Consumer quando i produttori sono anche i consumatori - Come posso terminare?

Desidero utilizzare ConcurrentBag/BlockingCollection ecc. Per eseguirlo in parallelo. In questo scenario, i consumatori della coda, sono anche i produttori per la coda!

Il mio problema è questo: Utilizzando BlockingCollection, posso scrivere in modo molto semplice la logica foreach per rimuovere gli elementi e accodarne di nuovi - Quando la coda è vuota, la raccolta di blocchi si blocca correttamente e aspetta che il nuovo lavoro venga prodotto da uno degli altri consumatori.

Ma come faccio a sapere se tutti i consumatori stanno bloccando ?!

Conosco CompleteAdding(), ma non sembra funzionare, poiché l'unica volta che si è effettivamente completati è quando tutti i produttori hanno finito di produrre e la coda è vuota e poiché tutti si bloccano, non c'è nessuno "libero" per impostare CompleteAdding(). C'è un modo per rilevare questo? (Forse un evento che può sparare quando si blocca e sparare di nuovo quando è sbloccato?)

Posso gestirlo manualmente, non usando un foreach, ma manualmente avendo un ciclo while (! Complete) e usando TryTake, ma poi ho bisogno di dormire manualmente, che sembra inefficace (l'intera ragione per avere la raccolta di blocchi vs solo le raccolte concorrenti in primo luogo!) Ogni volta che il ciclo, se TryTake è falso, potrei impostare un flag di inattività, e poi avere un controllo Master se la coda è vuota, e tutti i thread sono inattivi, impostare un flag completo, ma ancora una volta, sembra kludgy.

L'intuizione mi dice che esiste un modo per utilizzare Blocking Collection per farlo, ma non riesco a raggiungerlo.

In ogni caso, qualcuno ha un buon motivo per cui i consumatori sono i produttori e di essere in grado di rilevare quando rilasciare tutti i blocchi sarebbe terribile

+1

Buona domanda. Qualsiasi cosa con bandiere esterne o eventi sembra matura per le condizioni di gara. –

+0

I processori (consumatori/produttori combinati) hanno molto stato o richiedono molte risorse? Potresti ri-lanciare il problema in termini di creazione di 'Task's che eseguono ciascuno una sola iterazione? –

+0

@Damien_The_Unbeliever: Sì, posso fare un'unica iterazione, e in effetti ho già funzionato, ma sto provando a usare uno schema produttore/consumatore poiché questo è un codice che può essere migrato nel cloud in futuro, dove i ruoli dei lavoratori saranno utilizzando lo spazio di archiviazione di Azure Queue allo stesso modo e vorrei mantenere la logica generale il più simile possibile tra le due implementazioni. In questo scenario sarò costretto a controllare se i Lavoratori sono tutti inattivi per decidere che la coda sarà terminata, ma sembra che dovrei essere efficiente laddove possibile localmente - anche, voglio solo capirlo :) –

risposta

-3

Credo che questo link da MSDN ti può aiutare.

Reusable Parallel Data Structures and Algorithms

Espone come trattare con alcune strutture di dati in scenari simultanei.

+1

Le strutture dati del 2007 non rispondono alla mia domanda sulle librerie concorrenti 4.0 –

+0

Quindi implementalo tu stesso usando 4.0: è solo una guida, non la "risposta". – oarrivi

Problemi correlati