Reputation: 4116
I have been trying to get my head around the Blocking Collection and I came across Take()
and TryTake()
also Add()
and TryAdd()
I understand that if there are no items to take, Take()
will wait till an item is added, similarly with Add()
if the collection has reached its max limit, it will wait till the item is removed.
As per Josheph Albahari's article on Parallel Programming
"Add and TryAdd may block if the collection size is bounded; Take and TryTake block while the collection is empty."
So Take()
and TryTake()
both wait for an item to be added. So, if we are not providing any timeout or cancellation token, what is the difference between Take()
and TryTake()
, shouldn't TryTake()
return false
straightaway and not wait ? and same for TryAdd()
?
Upvotes: 8
Views: 6593
Reputation: 335
I stumbled upon this question and I think this document of Microsoft is really helpful to figure out what's happening behind the science.
If no item is present, maximum capacity on a bounded collection has been reached, or the timeout period has elapsed, then the TryAdd or TryTake operation returns false. This allows the thread to do some other useful work for a while and then try again later to either retrieve a new item or try to add the same item that could not be added previously.
How to Add and Take Items Individually from a BlockingCollection
Upvotes: 1
Reputation: 29632
Take
will signal completion of the queue by throwing an InvalidOperationException
. This makes debugging a bit hard if you have the exceptions tab configured to throw on caught exceptions.
Because of this, I did try to use TryTake
. It turns out that BlockingCollection<T>.Take
actually does use TryTake
, but with an infinite timeout. So instead of writing this:
while (!queue.IsCompleted)
{
object obj;
try
{
obj = queue.Take();
}
catch (InvalidOperationException)
{
continue;
}
// Do something with obj.
}
You can use TryTake
as follows:
while (!queue.IsCompleted)
{
if (!queue.TryTake(out var obj, Timeout.InfiniteTimeSpan))
continue;
// Do something with obj.
}
Makes the code a lot cleaner and doesn't throw the InvalidOperationException
.
Upvotes: 6