15

When calling BlockingCollection.Take() it is possible for the IsCompleted status of the collection to change between the check of IsCompleted and the call to Take().

The MSDN Documentation that shows an example just catches the invalid operation exception, but it seems like there must be a proper way to do such a call without catching the exception (since this incurs a decent amount of overhead and doesn't look clean in code). What is the proper way to call .Take() and to avoid an invalid operation exception?

A simplified version of my specific issue:

If (!blockingCollection.IsCompleted) { //do some stuff value = blockingCollection.Take(); //Throws Exception, IsCompleted = True; } 

There is a TryTake method available, but I am under the impression that it is so that a timeout and cancelation token can be passed in, not to deal with the IsCompleted becoming true in between the time it is checked and when Take() is called.

1 Answer 1

14

You can use the TryTake overload with no timeout/cancelation. It will return false if the BlockingCollection is empty or has been marked completed, and handles the synchronization issue you're facing correctly.

Sign up to request clarification or add additional context in comments.

3 Comments

I get a InvalidOperationException when calling TryTake while the collection is empty... (using a timeout tough but surly the time had not passed). How come?
@ilans, If you look at the docs, it says InvalidOperationException happens in TryTake when "The underlying collection was modified outside of this BlockingCollection<T> instance."
That overload won't block, which is often the whole point of using this collection. There is the less obvious choice of TryTake(out foo, Timeout.InfiniteTimeSpan) which will block just like Take does, unblocking on next item or when CompleteAdding is called.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.