Krzysztof K

Krzysztof K

  • NA
  • 4
  • 844

How to enumerate BlockingCollection not destroying elements?

Aug 19 2018 2:18 PM
I need to use a kinda-ConsumerProducer pattern (Queue-based), in which the Consumer threads do not in fact consume (destroy) the elements*, but instead a consumer thread can at any point ask for a handle to the beginning of the queue and start enumerating through it at its own speed. I can't use ConcurrentQueue because enumerating ConcurrentQueue works on its snapshot (taken when Enumerator has been requested), so the consumer threads would not see the elements which the producers add in the meantime.
 
It seemed to me BlockingCollection should've been the correct class to use, but it apparently offers only two types of Enumerators/Enumerables:
GetConsumingEnumerable(), which
  • destroys the elements (calls Dequeue)
  • works on the real version of the collection
BlockingCollection.IEnumerable, which
  • doesn't destroy the elements
  • works on the snapshot taken at the moment when Enumerator has been requested
The fact that BlockingCollection only offers those two combinations seems too restrictive to be usable in my scenario - I would need something which works on a real queue (like ConsumingEnumerable does) but only enumerates the elements without destroying (like BlockingCollection.IEnumerable does).
 
Question:
 
Could anyone advise if there is a way to achieve this without writing an own Queue implementation (which obviously I consider a rather discouraged thing to do when we talk about multi-thread environment) - can this be achieved using BlockingCollection, or does there exist some other collection that can support such behaviour?
 
[(*) In fact, one designated of the consumer threads might actually sometimes destroy elements (i.e. call Dequeue). However, I am fine if need to say that this action would have to invalidate all the other consumers' ongoing enumerations, so the question can be simplified to assuming that consumers do not Dequeue at all.]