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);
}
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With