BlockingCollection中Take/TryTake与Add/TryAdd的差异疑问
Great question—let’s unpack this clearly because BlockingCollection’s Try* methods can feel counterintuitive at first, especially when referencing Joseph Albahari’s notes.
Take() vs TryTake()
Let’s start with core behaviors, focusing on overloads with no timeout or cancellation token:
Take(): Straightforward—if the collection is empty, it blocks indefinitely waiting for an element to be added. It only throws anInvalidOperationExceptionif the collection is marked as completed (viaCompleteAdding()), meaning no more elements will ever be added.TryTake(out T item): This parameterless overload does NOT block. It checks instantly if an element is available: grabs it and returnstrueif yes; returnsfalseimmediately if the collection is empty (and not completed)—no waiting at all.
Wait, but Joseph’s note says "when the collection is empty, Take and TryTake will block"—that’s referring to the overloaded versions of TryTake() that accept a timeout or cancellation token, not the parameterless one. Those overloads (like TryTake(out T item, int millisecondsTimeout)) will block for the specified time waiting for an element, which matches his description. The parameterless TryTake is purely a "check-and-go" method.
Add() vs TryAdd()
The exact same logic applies to the Add/TryAdd pair:
Add(T item): If the collection hits its maximum capacity, this method blocks indefinitely until space opens up (when an element is removed). LikeTake(), it throwsInvalidOperationExceptionif the collection is marked as completed.TryAdd(T item)(parameterless): This checks instantly if there’s space available. It adds the item and returnstrueif yes; returnsfalseright away if the collection is full (and not completed)—no blocking.
Again, Joseph’s mention of "Add and TryAdd may block" refers to overloads with timeouts or cancellation tokens (like TryAdd(T item, CancellationToken)), which will wait for space instead of bailing immediately.
Quick Recap to Avoid Confusion
The critical difference boils down to which overload you’re using:
- Parameterless
TryTake()andTryAdd(): Never block—they’re instant checks that returntrue/falseright away. - Overloads with timeout or cancellation token: Can block (either for a set time or until canceled), which is what Joseph’s note is referencing.
It’s easy to mix up the overloads, which is why his statement might seem contradictory at first. The "blocking" behavior of Try* methods only kicks in when you explicitly ask them to wait.
内容的提问来源于stack exchange,提问作者Muds

