2

The following code never return. Debugging shows that the queue.IsCompleted returns false even when the queue is empty. Did I miss anything?

var workers = new Task[1];
using (var queue = new BlockingCollection<QueuePayload>(20))
{
    workers[0] = Task.Run(() => Consume(queue));
    queue.Add(new QueuePayload{....});
    Task.WaitAll(workers);
}

void Consume(BlockingCollection<QueuePayload> queue))
{
    while (!queue.IsCompleted)
    {
        var i = new QueuePayload();
        try
        {
            i = queue.Take();
        }
        catch (InvalidOperationException)
        {
            break;
        }
    ......
ca9163d9
  • 27,283
  • 64
  • 210
  • 413

2 Answers2

5

The property for IsCompleted at https://msdn.microsoft.com/en-us/library/dd267315(v=vs.110).aspx has the following text:

Whether this collection has been marked as complete for adding and is empty.

Where do you mark the collection as completed? This is not an empty check - it is an empty check with a manual additional switch.

There is accordingly a CompleteAdding() method that marks that no more items will be added.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
TomTom
  • 61,059
  • 10
  • 88
  • 148
  • Not sure who marked this down, but if the question is about why the `IsCompleted` flag is not returning `true` when the queue is empty it answers that question. – Berin Loritsch May 16 '16 at 18:18
1

When you're done adding items to the collection, call queue.CompleteAdding(). That way queue.IsCompleted will return true when there are no items in the collection (after you have removed them all.) If you don't call CompleteAdding() then there's a possibility that more items could be added, so IsCompleted will always return false.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62