2015-11-05 7 views
5

Credo che uno scenario piuttosto comune sia quello di avere una coda di elementi che dovrebbero essere elaborati N alla volta.Esiste una classe di coda .NET che consente di eliminare più elementi contemporaneamente?

Per esempio .. se abbiamo 23 items e dobbiamo elaborare 10 alla volta, sarebbe come:

Process batch of 10 
Process batch of 10 
Process batch of 3 

posso risolvere questo problema in un variaty di modi. La mia domanda è: il framework .NET fornisce una classe progettata specificamente per affrontare questo scenario? La classe Queue sarebbe perfetta ma non consente di eliminare più elementi contemporaneamente.

+2

Non puoi semplicemente annullare l'accodamento 10 articoli in un loop e poi elaborarli? Mi manca qualcosa dalla tua domanda che preclude questo approccio? – xxbbcc

+1

perché non accodate solo lotti completi di 10? – Carsten

+0

Sì. Non volevo farlo, ma in realtà non ci sono molte ragioni per questo. È solo brutto. Ma sì ... probabilmente dovrei farlo. –

risposta

10

È possibile creare un metodo di estensione sul Queue<T>:

public static class QueueExtensions 
{ 
    public static IEnumerable<T> DequeueChunk<T>(this Queue<T> queue, int chunkSize) 
    { 
     for (int i = 0; i < chunkSize && queue.Count > 0; i++) 
     { 
      yield return queue.Dequeue(); 
     } 
    } 
} 

Usage:

var q = new Queue<char>(); 
q.DequeueChunk(10) // first 10 items 
q.DequeueChunk(10) // next 10 items 

Esempio:https://dotnetfiddle.net/OTcIZX

+0

+1, grazie per la risposta. Credo che questo sia il più pulito. Ho accettato l'altro perché ho dichiarato qualcosa di built-in (evento anche se si tratta di una libreria di estensione) nella domanda. Grazie ancora. –

+1

Certo, ho pensato di aggiungere un'implementazione nel caso fosse utile a chiunque altro –

1

La libreria TPL Dataflow offre BatchBlock < T > che raggruppa la sequenza di input dei messaggi in blocchi della dimensione desiderata.

var bb = new BatchBlock<int>(10); 
var ab = new ActionBlock<int[]>((Action<int[]>)chunk=>HandleChunk(chunk)); 

bb.LinkTo(ab, new DataflowLinkOptions(){PropogateCompletion = true}); 

for(int i = 0; i < 23; ++i) 
{ 
    bb.Post(i); 
} 

bb.Complete(); 
ab.Completion.Wait(); 
+0

grazie per la risposta. Solo così sono chiaro: quando invii i dati a un 'BatchBlock' a cui stai assegnando i dati da elaborare. Ma solo 10 saranno elaborati alla volta. Quindi probabilmente, 'Post' bloccherà il thread finché non torneranno alcuni degli elementi. Destra? O è parallelo? Probabilmente è parallelo perché proviene dalla libreria TPL –

+0

@andrerpena Che è corretto. Di default ActionBlock elabora i messaggi in modo sequenziale. È possibile modificare questo comportamento specificando MaxDegreeOfParalIelism nelle opzioni. – alexm

+0

Capisco. Grazie. Quindi, suppongo che l'azione 'chunk => HandleChunck (chunk)' sarà eseguita per ogni 10 elementi (il chunk sarà di 10 elementi). Tuttavia, come fa a sapere che dovrebbe elaborare gli ultimi 3 anche se non abbiamo raggiunto i 30? È a causa del metodo completo? Il processo inizierà solo quando viene chiamato il Completo? –