Como consumir um BlockingCollection em lotes

Eu criei algum código para consumir todos os itens desejados de uma fila. Em vez de processar os itens 1 por 1, faz sentido processar todos os itens em espera como um conjunto.

Eu declarei minha fila assim.

private BlockingCollection items = new BlockingCollection(new ConcurrentQueue); 

Então, em um segmento consumidor, eu pretendo ler os itens em lotes como este,

 Item nextItem; while (this.items.TryTake(out nextItem, -1)) { var workToDo = new List(); workToDo.Add(nextItem); while(this.items.TryTake(out nextItem)) { workToDo.Add(nextItem); } // process workToDo, then go back to the queue. } 

Essa abordagem não tem o utilitário GetConsumingEnumerable e não posso deixar de me perguntar se perdi uma maneira melhor ou se minha abordagem é falha.

Existe uma maneira melhor de consumir um BlockingCollection em lotes?

    Embora não seja tão bom quanto ConcurrentQueue em alguns aspectos, meu próprio LLQueue permite um retraimento em lote com um método AtomicDequeueAll em que todos os itens atualmente na fila são retirados dele em uma única operação (atômica e thread-safe) e, em seguida, estão em uma coleção não thread-safe para consumo por um único thread. Esse método foi projetado precisamente para o cenário em que você deseja agrupar as operações de leitura.

    Isso não está bloqueando, embora possa ser usado para criar uma coleção de bloqueio com bastante facilidade:

     public BlockingBatchedQueue { private readonly AutoResetEvent _are = new AutoResetEvent(false); private readonly LLQueue _store; public void Add(T item) { _store.Enqueue(item); _are.Set(); } public IEnumerable Take() { _are.WaitOne(); return _store.AtomicDequeueAll(); } public bool TryTake(out IEnumerable items, int millisecTimeout) { if(_are.WaitOne(millisecTimeout)) { items = _store.AtomicDequeueAll(); return true; } items = null; return false; } } 

    Esse é um ponto de partida que não faz o seguinte:

    1. Lidar com um leitor de espera pendente após a eliminação.
    2. Preocupe-se com uma corrida em potencial com múltiplos leitores, ambos sendo desencadeados por uma gravação acontecendo enquanto a pessoa estava lendo (apenas considera o resultado vazio ocasional enumerável estar ok).
    3. Coloque qualquer limite superior na escrita.

    Tudo o que poderia ser adicionado também, mas eu queria manter o mínimo de algum uso prático, que esperamos que não seja buggy dentro das limitações definidas acima.