Parallel Computing Developer Center >
Parallel Computing Forums
>
Parallel Extensions to the .NET Framework
>
When BlockingCollection<T>.TakeFromAny() return -1?
When BlockingCollection<T>.TakeFromAny() return -1?
- Hi2all!
I have one question: when BlockingCollection<(Of <T>)>.TakeFromAny() static method return -1?
I read MSDN Docs that TakeFromAny() returns:
The index of the collection in the collections array from which the item was removed, or -1 if an item could not be removed.
Ok, but when item couldn't be removed? When collections parameter array contains empty not completed BlockingCollection<T> instances, the thread, called TakeFromAny() is blocked.
Let me to show you an example. I have console application:
using System; using System.Collections.Generic; //using System.Linq; using System.Text; using System.Collections.Concurrent; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { BlockingCollection<int> col1 = new BlockingCollection<int>(); BlockingCollection<int> col2 = new BlockingCollection<int>(); //Timer t1 = new Timer(delegate // { // // col1.Add(111); // col1.CompleteAdding(); // }, null, 1000, Timeout.Infinite); //Timer t2 = new Timer(delegate // { // //col2.Add(222); // //Thread.SpinWait(30000000); // col2.CompleteAdding(); // }, null, 2000, Timeout.Infinite); Console.WriteLine(DateTime.Now.ToLongTimeString()); int value; int indexOfCollection = BlockingCollection<int>.TakeFromAny(new[] { col1, col2 }, out value); Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + value + " index = "+indexOfCollection); Console.WriteLine("Done"); Console.ReadLine(); } } }
In this case main app thread is blocked forever. If I uncomment lines with 2 timers creation, I have ArgumentException : At least one of the specified collections is marked as complete with regards to additions.
Parameter name: collections
If I uncomment additional lines, where call Add method to both collections - it's ok, I take 111 value from col1.
So I can't imagine situation, where TryTakeFrom() returns -1. Can you explain me, when it's possible?
Thanks in advance!
P.S. My Env: windows 2008 R2 RC, VS 2010 beta 2.- Edited byVitaly DilmukhametovMVPTuesday, October 20, 2009 4:05 PMcode sample render issues
Answers
- I filed Feedback on Connect for this issue. I believe it is just a documentation issue, as TryTakeFromAny provides the -1 behavior, and TakeFromAny's behavior seems reasonable.
Reed Copsey, Jr. - http://reedcopsey.com- Marked As Answer byStephen Toub - MSFTMSFT, ModeratorWednesday, October 21, 2009 2:25 PM
All Replies
- TakeFromAny() and TryTakeFromAny() will return -1 if the collections are all in a valid state, but are all empty (they've had CompleteAdding() called, but have already had all of their elements removed).
Once the collections have had CompleteAdding() called, they no longer block on remove attempts if the collection is empty. If all of the collections are this way, your "Take.." methods will not block, but not succeed, and will return -1.
Typically, this happens when you're task(s) are complete, since you've processed all of the items in all of the collections...
Reed Copsey, Jr. - http://reedcopsey.com - Ok, I have 2 collections, which are empty and "completed", and I call TakeFromAny:
And I have the same ArgumentException with the same message.using System; using System.Collections.Generic; //using System.Linq; using System.Text; using System.Collections.Concurrent; namespace ConsoleApplication67 { class Program { static void Main(string[] args) { BlockingCollection<int> col1 = new BlockingCollection<int>(); BlockingCollection<int> col2 = new BlockingCollection<int>(); //col1.Add(1); col1.CompleteAdding(); col2.CompleteAdding(); int val = 0; Console.WriteLine(BlockingCollection<int>.TakeFromAny(new[] { col1, col2 }, out val)); Console.WriteLine("Done"); Console.ReadLine(); } } }
When I uncomment col1.Add(1); line, I succesfully take element 1 from col1.
So, in this case TakeAnyFrom also don't return -1.
If I understand you incorrectly, please let me know. Thank you for reply!- Edited byVitaly DilmukhametovMVPTuesday, October 20, 2009 5:20 PMcode sample rendering issue
- I apologize - and I see your point. I don't believe TakeAnyFrom, from what I can see, will ever return -1.
I was thinking of TryTakeFromAny, which does return -1. For example:
namespace ConsoleApplication1 { using System; using System.Collections.Concurrent; class Program { static void Main(string[] args) { BlockingCollection<int> col1 = new BlockingCollection<int>(); BlockingCollection<int> col2 = new BlockingCollection<int>(); int val = 0; Console.WriteLine(BlockingCollection<int>.TryTakeFromAny(new[] { col1, col2 }, out val)); Console.WriteLine("Done"); Console.ReadLine(); } } }
This prints -1 immediately.
Reed Copsey, Jr. - http://reedcopsey.com - I filed Feedback on Connect for this issue. I believe it is just a documentation issue, as TryTakeFromAny provides the -1 behavior, and TakeFromAny's behavior seems reasonable.
Reed Copsey, Jr. - http://reedcopsey.com- Marked As Answer byStephen Toub - MSFTMSFT, ModeratorWednesday, October 21, 2009 2:25 PM
- Great! Thank you for support.
I think it's "copy-paste" documentation issue too. And TakeFromAny() doesn't return -1, because it return index on success, generate an exception in some cases, or wait for element continiously. - Great find Vitaly!
I've filed a documentation bug to get this corrected. This includes removing the reference to -1 and documenting the exception that might be thrown if you pass a BlockingCollection<T> that has had CompletedAdding called on it and been passed to TakeFromAny.
Josh


