0

I'm looking for a collection object similar to BlockingCollection that will let me have multiple consumers. However, I need those multiple consumers to consume ALL the items. They cannot remove items from it. Essentially, I need to be able to add items to it from another thread and expect anybody who obtains an Enumerator to scroll through all items ever added. And block until it's closed.

Is there such a collection type anywhere?

[EDIT] Good lord, guess I'll clarify... BlockingCollection.GetConsumingEnumerable() returns enumerables that block enumeration when items are not available, or until CompleteAdding is called. I want the SAME THING, except without removing items from the collection.

[EDIT] Okay. Whatever. I solved this: by writing my own blocking list.

Jerome Haltom
  • 1,670
  • 2
  • 17
  • 23
  • 1
    So it would need to buffer all items ever created? – Jon Skeet Feb 01 '13 at 07:11
  • If they don't .Take() then the item is still there. You could write a custom collection that implements BlockingCollection and take away Take(). – paparazzo Feb 01 '13 at 14:40
  • @JonSkeet Yes. Basically, I am streaming some results in from the network and expect the user to obtain multiple Enumerators to this data as if it was a "real" enumerable. However he might obtain multiple. – Jerome Haltom Feb 02 '13 at 22:01
  • -1 Asked for clarification on "block until it's closed". Response "exactly like Exactly as BlockingCollection operates". But you ask for "I also want all enumerators to block until the collection is closed". That is NOT how a blocking collection operates. – paparazzo Feb 07 '13 at 01:47
  • I clarified. I think. I didn't imagine this question was that hard to understand. – Jerome Haltom Feb 11 '13 at 02:31

1 Answers1

1

Essentially, I need to be able to add items to it from another thread and expect anybody who obtains an Enumerator to scroll through all items ever added.

You can directly use BlockingCollection<T>, but make sure that "consumers" just enumerate the collection itself rather than the result of GetConsumingEnumerable().

From MSDN:

Unlike GetConsumingEnumerable, BlockingCollection.IEnumerable.GetEnumerator returns a standard enumerator that does not modify the underlying collection.

var collection = new BlockingCollection<int> { 5, 12, 20 };

//5, 12, 20
foreach (var i in collection)
{
    Console.WriteLine(i);
}

collection.Add(6);

// 5, 12, 20, 6
foreach (var i in collection)
{
    Console.WriteLine(i);
}

And block until it's closed.

Do you mean you want to block items from being added while there is an open enumerator on the collection? Why? This is doable of course (e.g. a collection backed by ReaderWriterLockSlim).

Ani
  • 111,048
  • 26
  • 262
  • 307
  • Hmm. Does it block until closed? I was under the impression that the standard enumerator simply exited when no more records were available. Your example is right on the money of what I want, except I also want all enumerators to block until the collection is closed. – Jerome Haltom Feb 02 '13 at 21:45
  • http://msdn.microsoft.com/en-us/library/dd287186.aspx Buried in the example on that page is this text: former will block waiting for completion and the latter will simply take a snapshot of the current state of the underlying collection. – Jerome Haltom Feb 02 '13 at 21:58
  • To clarify, no I don't want to block adders. I want to block consumers. – Jerome Haltom Feb 02 '13 at 22:04
  • @wasabi Clarify the question. Define block until is is closed. – paparazzo Feb 05 '13 at 20:26
  • @Blam Exactly as BlockingCollection operates. – Jerome Haltom Feb 07 '13 at 01:09