Search code examples
c#blockingcollection

Does BlockingCollection re-try if its underlying collection is not empty but TryTake fails?


BlockingCollection is a wrapper around IProducerConsumerCollection. My understanding is that calling BlockingCollection.Take checks if there is an item available (using its own counter). Then it uses TryTake on its underlying collection to retrieve said item.

Now of course there has to actually exist an item in the underlying collection (and no external modification happening). But what happens if TryTake fails for some other reason, and the underlying collection returns false to TryTake? Does the wrapper just give up, or does it try to take the item again (supposedly succeeding next time)?

The ominous "other reason" could be an internal delay e.g. if the data structure is distributed.


Solution

  • Well, the only thing you can definitely take for granted is what's written in the documentation. But you can just take a look at the source code:

    public T Take()
    {
        T item;
    
        if (!TryTake(out item, Timeout.Infinite, CancellationToken.None))
        {
            throw new InvalidOperationException(SR.GetString(SR.BlockingCollection_CantTakeWhenDone));
        }
    
        return item;
    }
    

    In other words, the reason why TryTake returns false is irrelevant; Take will throw.