BlockingCollection provides an easier alternative for looping through a collection, and removing items without setting up a while loop, and checking the IsCompleted property. BlockingCollection gives us the ability to do a simple foreach loop with the GetConsumingEnumerable method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Concurrent;

//
// .NET 4.5 Parallel Extensions Cookbook
// Chapter 5: Iterating a BlockingCollection with GetConsumingEnumerable
//
// BlockingCollection provides us with an easier alternative for looping through
// a collection, and removing items without setting up a while loop, and
// checking the IsCompleted property. BlockingCollection gives us the ability to
// do a simple foreach loop with the GetConsumingEnumerable method.
//
// In this recipe, we are going to create a Console application that initializes
// a range of source data and spins up a producer task to add the data to the
// collection. The consumer of the collection data will use the
// GetConsumingEnumerable method to get IEnumerable<T> for items in the
// collection.
//
// https://www.packtpub.com/application-development/net-45-parallel-extensions-cookbook
//

namespace EnumerateCollection
{
    class Program
    {
        static void Main()
        {
            var numbers = Enumerable.Range(0, 100);
            var result = new BlockingCollection<long>(1000);
            var tasks = new List<Task>();

            // Producer
            var producer = Task.Factory.StartNew(() =>
            {
                foreach (var item in numbers)
                {
                    result.Add(item);
                    Console.WriteLine("Adding:{0} Item Count={1}", item, result.Count());
                }

                result.CompleteAdding();
            });

            // Consumer
            var consumer = Task.Factory.StartNew(() =>
            {
                foreach (var item in result.GetConsumingEnumerable())
                {
                    Console.WriteLine("Consuming item: {0}", item);
                }
            });

            tasks.Add(producer);
            tasks.Add(consumer);

            try
            {
                Task.WaitAll(tasks.ToArray());
            }
            catch (AggregateException ae)
            {
                foreach (var v in ae.InnerExceptions)
                {
                    Console.WriteLine(v.Message);
                }
            }

            // Console.ReadLine();
            // Task.WaitAll(producer, consumer);
        }
    }
}