Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When can BlockingCollection<T> TryTake() return false?

Assuming the BlockingCollection is using a ConcurrentQueue underneath, when could the TryTake(T, Int32) method return false if you are using Timeout.Infinite?

like image 798
Gyrien Avatar asked Jan 17 '14 20:01

Gyrien


2 Answers

Here's a simple example that shows when it can return false: when the collection is marked as CompleteAdding and becomes emptу

//by default, BlockingCollection will use ConcurrentQueue
BlockingCollection<int> coll = new BlockingCollection<int>();

coll.Add(1);
coll.Add(2);
coll.CompleteAdding();

int item;

if (coll.TryTake(out item, -1))
{
    Console.WriteLine(item);
}

if (coll.TryTake(out item, -1))
{
    Console.WriteLine(item);
}

if (coll.TryTake(out item, -1))
{
    //this won't get hit
}
else
{
    Console.WriteLine("TryTake returned false!");
}

This allows you to forbid adding new items in queue and complete processing of remaining elements

like image 136
Sven Grosen Avatar answered Nov 07 '22 17:11

Sven Grosen


This will print false :

 var coll = new BlockingCollection<int>();            

 coll.CompleteAdding();   // closed for business

 int v;
 bool result = coll.TryTake(out v, Timeout.Infinite);

 Console.WriteLine(result);

So basically a BlockingCollection supports 2 separate concepts: Empty and Closed. And while TryTake() can wait forever on an Empty queue, when the queue is both Empty and Closed it will return false.

like image 34
Henk Holterman Avatar answered Nov 07 '22 17:11

Henk Holterman