I was trying out BlockingCollection<T>
(as a Queue) in .NET8 and sometimes I end up with the exception:
"System.InvalidOperationException: The collection argument is empty and has been marked as complete with regards to additions."
Code example:
private static void TestMethod()
{
using BlockingCollection<DummyClass> queue = new BlockingCollection<DummyClass>();
var task = Task.Run(() => //Produce
{
for (int i = 0; i < 10000000; i++)
{
queue.Add(new DummyClass());
}
queue.CompleteAdding();
});
int counter = 0;
try
{
while (!queue.IsCompleted) //Consume
{
DummyClass item = queue.Take(); // <-- Sometimes exception here
counter++;
}
Console.WriteLine($"counter={counter} ");
}
catch (Exception ex)
{
Console.WriteLine("Error:" + ex.ToString());
}
}
IsCompleted states "Whether this collection has been marked as complete for adding and is empty."
So as long as CompleteAdding() has not been called Take() should be blocking and when CompleteAdding() has been called and the queue is empty, " !queue.IsCompleted " should return false.
What am I missing?
Any help would be very much appreciated.
Running in VS2022 17.8.5 on Windows 11.
You have a thread race; imagine:
queue.CompleteAdding();
while (!queue.IsCompleted)
Take()
and boom
Solution: use TryTake