Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TryTake vs GetConsumingEnumerable

What is the difference between solution 1 and 2, _taskQ is BlockingCollection and I am trying to implement a Producer-Consumer scenario. The BlockingCollection uses the default ConcurrentQueue for internal storage.

//Solution 1
foreach (Action action in _taskQ.GetConsumingEnumerable())
{
    action(); // Perform task.
    Thread.Sleep(1000);
}

TryTake blocks when there is no item

//Solution 2
Action t;
while(_taskQ.TryTake(out t))
{
    t();
    Thread.Sleep(1000);
}
like image 724
Helic Avatar asked Feb 04 '16 16:02

Helic


People also ask

What is a BlockingCollection?

BlockingCollection<T> is a thread-safe collection class that provides the following features: An implementation of the Producer-Consumer pattern. Concurrent adding and taking of items from multiple threads. Optional maximum capacity. Insertion and removal operations that block when collection is empty or full.

Is Blockcollection a FIFO?

That being said, BlockingCollection<T> works upon any IProducerConsumerCollection<T> (specified in the constructor). If you don't provide one in the constructor, internally, it will use a ConcurrentQueue<T> . This causes it to be FIFO, since it will actually be (internally) a queue.


1 Answers

bool TryTake(out T) returns false immediately if there are no items.
bool TryTake(out T, TimeSpan) returns false if there are no items within the timeout period. The enumerable returned by GetConsumingEnumerable() blocks while it has no items, until a producer calls CompleteAdding().

In Solution 1, you wait for the next action and execute it; a suitable pattern! But the Thread.Sleep() is not really necessary because the iteration will block if there are no items anyway.

In Solution 2, you take and execute actions while there are any, then exit the loop if the consumer gets ahead of the producer. That's probably not what you want.

like image 56
piedar Avatar answered Sep 29 '22 08:09

piedar