Example #1
0
        private async Task Run()
        {
            var sw = new SpinWait();

            while (!_input.All(bc => bc.IsCompleted) && !_token.IsCancellationRequested)
            {
                var i = BlockingCollection <TInput> .TryTakeFromAny(_input, out var receivedItem, 50, _token);

                if (i >= 0)
                {
                    TOutput outputItem =
                        _processor != null?_processor(receivedItem) : await _processoTask(receivedItem);

                    BlockingCollection <TOutput> .AddToAny(Output, outputItem);

                    sw.SpinOnce();
                }
                else
                {
                    Thread.SpinWait(1000);
                }
            }

            if (Output != null)
            {
                foreach (var bc in Output)
                {
                    bc.CompleteAdding();
                }
            }
        }
Example #2
0
        public static bool ExternalCancel_AddToAny()
        {
            TestHarness.TestLog("* BlockingCollectionCancellationTests.ExternalCancel_AddToAny()");
            bool passed = true;

            BlockingCollection <int> bc1 = new BlockingCollection <int>(1);
            BlockingCollection <int> bc2 = new BlockingCollection <int>(1);

            bc1.Add(1); //fill the bc.
            bc2.Add(1); //fill the bc.

            CancellationTokenSource cs = new CancellationTokenSource();

            ThreadPool.QueueUserWorkItem(
                (obj) =>
            {
                Thread.Sleep(100);
                cs.Cancel();
            });

            passed &= TestHarnessAssert.IsFalse(cs.IsCancellationRequested, "At this point the cancel should not have occurred.");
            passed &= TestHarnessAssert.EnsureOperationCanceledExceptionThrown(
                () => BlockingCollection <int> .AddToAny(new [] { bc1, bc2 }, 1, cs.Token),
                cs.Token,
                "The operation should wake up via token cancellation.");

            return(passed);
        }
        public static void ExternalCancel_AddToAny()
        {
            for (int test = 0; test < 3; test++)
            {
                BlockingCollection <int> bc1 = new BlockingCollection <int>(1);
                BlockingCollection <int> bc2 = new BlockingCollection <int>(1);
                bc1.Add(1); //fill the bc.
                bc2.Add(1); //fill the bc.

                // This may or may not cancel before {Try}AddToAny executes, but either way the test should pass.
                // A delay could be used to attempt to force the right timing, but not for an inner loop test.
                CancellationTokenSource cs = new CancellationTokenSource();
                Task.Run(() => cs.Cancel());
                Assert.Throws <OperationCanceledException>(() =>
                {
                    switch (test)
                    {
                    case 0:
                        BlockingCollection <int> .AddToAny(new[] { bc1, bc2 }, 42, cs.Token);
                        break;

                    case 1:
                        BlockingCollection <int> .TryAddToAny(new[] { bc1, bc2 }, 42, Timeout.Infinite, cs.Token);
                        break;

                    case 2:
                        BlockingCollection <int> .TryAddToAny(new[] { bc1, bc2 }, 42, (int)TimeSpan.FromDays(1).TotalMilliseconds, cs.Token);
                        break;
                    }
                });
                Assert.True(cs.IsCancellationRequested);
            }
        }
        public void Run()
        {
            while (!Input.All(inputBC => inputBC.IsCompleted) && !_token.IsCancellationRequested)
            {
                TInput item;
                int    i = BlockingCollection <TInput> .TryTakeFromAny(Input, out item, TIMEOUT, _token);

                if (i >= 0)
                {
                    if (Output != null)
                    {
                        TOutput result = _processor(item);
                        BlockingCollection <TOutput> .AddToAny(Output, result, _token);
                    }
                    else
                    {
                        _outputProcessor(item);
                    }
                }
            }
            if (Output != null)
            {
                foreach (var outputBC in Output)
                {
                    outputBC.CompleteAdding();
                }
            }
        }
Example #5
0
        public static void UsingMultipleBlockingCollection()
        {
            BlockingCollection <string> bc1 = new BlockingCollection <string>();
            BlockingCollection <string> bc2 = new BlockingCollection <string>();

            BlockingCollection <string> bc3 = new BlockingCollection <string>();

            BlockingCollection <string>[] bc1andbc2 = { bc1, bc2 };
            BlockingCollection <string>[] bcAll     = { bc1, bc2, bc3 };

            CancellationTokenSource tokenSource = new CancellationTokenSource();

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        string message = String.Format("Message from task {0}", Task.CurrentId);
                        BlockingCollection <string> .AddToAny(bc1andbc2, message, tokenSource.Token);
                        tokenSource.Token.WaitHandle.WaitOne(1000);
                    }
                }, tokenSource.Token);
            }

            for (int i = 0; i < 3; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        string warning = String.Format("Warning from task {0}", Task.CurrentId);
                        bc3.Add(warning, tokenSource.Token);
                        tokenSource.Token.WaitHandle.WaitOne(500);
                    }
                }, tokenSource.Token);
            }

            for (int i = 0; i < 2; i++)
            {
                Task consumer = Task.Factory.StartNew(() =>
                {
                    string item;
                    while (!tokenSource.IsCancellationRequested)
                    {
                        int bcid = BlockingCollection <string> .TakeFromAny(bcAll, out item, tokenSource.Token);
                        Console.WriteLine("From collection {0} : {1}", bcid, item);
                    }
                }, tokenSource.Token);
            }

            Console.WriteLine("Press enter to cancel tasks");
            Console.ReadLine();

            tokenSource.Cancel();

            EndofProgram();
        }
Example #6
0
            public void Run()
            {
                WriteLine($"{Name} is runing!");
                //确定是否对序列中的所有元素都满足条件
                while (!_input.All(bc => bc.IsCompleted) && !_token.IsCancellationRequested)
                {
                    TInput receivedItem;
                    //尝试从任一指定的BlockingCollection实例中移除一个项。
                    //从其中一个集合中移除的项。
                    //等待的毫秒数,或为 System.Threading.Timeout.Infinite (-1),表示无限期等待。
                    //要观察的取消标记。
                    //从其中移除项的集合在 collections 数组中的索引;如果未能移除项,则为 -1。
                    int i = BlockingCollection <TInput> .TryTakeFromAny(_input, out receivedItem, 50, _token);

                    //移除成功
                    if (i >= 0)
                    {
                        if (Output != null)
                        {
                            TOutput outputItem = _processor(receivedItem);
                            BlockingCollection <TOutput> .AddToAny(Output, outputItem);

                            WriteLine($"{Name} sent {outputItem} to next,on"
                                      + $"Thread id {CurrentThread.ManagedThreadId}");
                            Sleep(TimeSpan.FromMilliseconds(_rnd.Next(200)));
                        }
                        else
                        {
                            _outputProcessor(receivedItem);
                        }
                    }
                    else
                    {
                        Sleep(TimeSpan.FromMilliseconds(50));
                    }
                }
                if (Output != null)
                {
                    foreach (var bc in Output)
                    {
                        bc.CompleteAdding();
                    }
                }
            }
Example #7
0
        public static void ExternalCancel_Negative()
        {
            BlockingCollection <int> bc = new BlockingCollection <int>(); //empty collection.

            CancellationTokenSource cs = new CancellationTokenSource();

            Task.Run(() => cs.Cancel());

            int item;

            EnsureOperationCanceledExceptionThrown(
                () => bc.Take(cs.Token), cs.Token,
                "ExternalCancel_Take:  The operation should wake up via token cancellation.");
            EnsureOperationCanceledExceptionThrown(
                () => bc.TryTake(out item, 100000, cs.Token), cs.Token,
                "ExternalCancel_TryTake:  The operation should wake up via token cancellation.");
            EnsureOperationCanceledExceptionThrown(
                () => bc.Add(1, cs.Token), cs.Token,
                "ExternalCancel_Add:  The operation should wake up via token cancellation.");
            EnsureOperationCanceledExceptionThrown(
                () => bc.TryAdd(1, 100000, cs.Token), // a long timeout.
                cs.Token,
                "ExternalCancel_TryAdd:  The operation should wake up via token cancellation.");

            BlockingCollection <int> bc1 = new BlockingCollection <int>(1);
            BlockingCollection <int> bc2 = new BlockingCollection <int>(1);

            bc1.Add(1); //fill the bc.
            bc2.Add(1); //fill the bc.
            EnsureOperationCanceledExceptionThrown(
                () => BlockingCollection <int> .AddToAny(new[] { bc1, bc2 }, 1, cs.Token),
                cs.Token,
                "ExternalCancel_AddToAny:  The operation should wake up via token cancellation.");
            EnsureOperationCanceledExceptionThrown(
                () => BlockingCollection <int> .TryAddToAny(new[] { bc1, bc2 }, 1, 10000, cs.Token),
                cs.Token,
                "ExternalCancel_AddToAny:  The operation should wake up via token cancellation.");

            IEnumerable <int> enumerable = bc.GetConsumingEnumerable(cs.Token);

            EnsureOperationCanceledExceptionThrown(
                () => enumerable.GetEnumerator().MoveNext(),
                cs.Token, "ExternalCancel_GetConsumingEnumerable:  The operation should wake up via token cancellation.");
        }
Example #8
0
        private static void UsingMultipleBlockingCollectionInstances()
        {
            var bc1 = new BlockingCollection <string>();
            var bc2 = new BlockingCollection <string>();
            var bc3 = new BlockingCollection <string>();

            var bc1And2 = new [] { bc1, bc2 };
            var bcAll   = new [] { bc1, bc2, bc3 };

            var tokenSource = new CancellationTokenSource();

            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        var message = string.Format($"Message from task {Task.CurrentId}");

                        BlockingCollection <string> .AddToAny(bc1And2, message, tokenSource.Token);
                        tokenSource.Token.WaitHandle.WaitOne(1000);
                    }
                }, tokenSource.Token);
            }

            for (int j = 0; j < 3; j++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        int bcId =
                            BlockingCollection <string>
                            .TakeFromAny(bcAll, out var item, tokenSource.Token);

                        Console.WriteLine($"From collection {bcId}: {item}");
                    }
                }, tokenSource.Token);
            }

            Console.WriteLine("Press enter to cancel tasks...");
            Console.ReadLine();
            tokenSource.Cancel();
        }
            public void Run()
            {
                Console.WriteLine($"{Name} is run");
                while (!_intput.All(bc => bc.IsCompleted) &&
                       !_token.IsCancellationRequested)
                {
                    TInput receivedItem;
                    int    i = BlockingCollection <TInput> .TryTakeFromAny(
                        _intput, out receivedItem, 50, _token);

                    if (i >= 0)
                    {
                        if (Output != null)
                        {
                            TOutput outputItem = _processor(receivedItem);
                            BlockingCollection <TOutput> .AddToAny(Output, outputItem);

                            Console.WriteLine($"{Name} sent {outputItem} to next, on thread id {Thread.CurrentThread.ManagedThreadId}");
                            Thread.Sleep(TimeSpan.FromMilliseconds(_rnd.Next(200)));
                        }
                        else
                        {
                            _outputProcessor(receivedItem);
                        }
                    }
                    else
                    {
                        Thread.Sleep(TimeSpan.FromMilliseconds(50));
                    }
                }

                if (Output != null)
                {
                    foreach (var bc in Output)
                    {
                        bc.CompleteAdding();
                    }
                }
            }
Example #10
0
        public void Process()
        {
            Console.WriteLine($"{Name} is running");

            while (!inputValues.All(bc => bc.IsCompleted) && !ct.IsCancellationRequested)
            {
                TInput inputItem;
                int    i = BlockingCollection <TInput> .TryTakeFromAny(inputValues, out inputItem, 50, ct);

                if (i >= 0)
                {
                    if (outputValues != null)
                    {
                        TOutput outputItem = processor(inputItem);
                        BlockingCollection <TOutput> .AddToAny(outputValues, outputItem);

                        Console.WriteLine($"{Name} sent {outputItem} to next");
                    }
                    else
                    {
                        outputProcessor(inputItem);
                    }
                }
                else
                {
                    Console.WriteLine("Unable to retrieve data from previous filter");
                }
            }

            // Marks the all BlockingCollection<T> instances as not accepting any more additions
            if (outputValues != null)
            {
                foreach (var bc in outputValues)
                {
                    bc.CompleteAdding();
                }
            }
        }
            public void Run()
            {
                Console.WriteLine("{0} is running", Name);
                while (!_input.All(i => i.IsCompleted) && !_token.IsCancellationRequested)
                {
                    TInput receivedItem;
                    int    i = BlockingCollection <TInput> .TryTakeFromAny(_input, out receivedItem, 50, _token);

                    if (i >= 0)
                    {
                        if (Output != null)
                        {
                            TOutput outputItem = _processor(receivedItem);
                            BlockingCollection <TOutput> .AddToAny(Output, outputItem);

                            Console.WriteLine("{0} sent {1} to next,线程id {2}", Name, outputItem,
                                              Thread.CurrentThread.ManagedThreadId);
                            Thread.Sleep(TimeSpan.FromMilliseconds(100));
                        }
                        else
                        {
                            _outputProcessor(receivedItem);
                        }
                    }
                    else
                    {
                        Thread.Sleep(TimeSpan.FromMilliseconds(50));
                    }
                }
                if (Output != null)
                {
                    foreach (var bc in Output)
                    {
                        bc.CompleteAdding();
                    }
                }
            }
Example #12
0
        public void Run()
        {
            Console.WriteLine("filter {0} is running", this.Name);
            while (!m_inputData.All(bc => bc.IsCompleted))
            {
                TInput receivedItem;
                int    i = BlockingCollection <TInput> .TryTakeFromAny(
                    m_inputData, out receivedItem, 50);

                if (i >= 0)
                {
                    if (m_outputData != null)
                    {
                        TOutput outputItem = m_function(receivedItem);
                        BlockingCollection <TOutput> .AddToAny(m_outputData, outputItem);

                        Console.WriteLine("{0} sent {1} to next filter", this.Name, outputItem);
                    }
                    else
                    {
                        m_outputAction(receivedItem);
                    }
                }
                else
                {
                    Console.WriteLine("Could not get data from previous filter");
                }
            }

            if (m_outputData != null)
            {
                foreach (var bc in m_outputData)
                {
                    bc.CompleteAdding();
                }
            }
        }
Example #13
0
        public void Run()
        {
            Console.WriteLine("{0} is running", this.Name);
            while (!m_input.All(bc => bc.IsCompleted) && !m_token.IsCancellationRequested)
            {
                TInput receivedItem;
                int    i = BlockingCollection <TInput> .TryTakeFromAny(
                    m_input, out receivedItem, 50, m_token);

                if (i >= 0)
                {
                    if (m_output != null) // we pass data to another blocking collection
                    {
                        TOutput outputItem = m_processor(receivedItem);
                        BlockingCollection <TOutput> .AddToAny(m_output, outputItem);

                        Console.WriteLine("{0} sent {1} to next", this.Name, outputItem);
                    }
                    else // we're an endpoint
                    {
                        m_outputProcessor(receivedItem);
                    }
                }
                else
                {
                    Console.WriteLine("Unable to retrieve data from previous filter");
                }
            }
            if (m_output != null)
            {
                foreach (var bc in m_output)
                {
                    bc.CompleteAdding();
                }
            }
        }
        public void AddAnyCancellable()
        {
            const int elNumber  = 5;
            const int colNumber = 5;

            var cols = new BlockingCollection <int> [colNumber];

            for (var i = 0; i < colNumber; i++)
            {
                cols[i] = new BlockingCollection <int> (elNumber);
            }

            var token = new CancellationTokenSource(1000);

            for (var i = 0; i < colNumber * elNumber; i++)
            {
                BlockingCollection <int> .AddToAny(cols, 1, token.Token);
            }

            foreach (var col in cols)
            {
                Assert.AreEqual(elNumber, col.Count);
            }
        }
Example #15
0
    public static async Task ThrottleProcessingAsync <T>(this IEnumerable <T> inputs, int parallel, Func <T, Task> process)
    {
        var queues = new BlockingCollection <T> [parallel];
        var tasks  = new Task[parallel];

        for (int i = 0; i < parallel; i++)
        {
            var queue = queues[i] = new BlockingCollection <T>(1);
            tasks[i] = Task.Run(async() =>
            {
                foreach (var input in queue.GetConsumingEnumerable())
                {
                    await process(input).ConfigureAwait(false);
                }
            });
        }
        try
        {
            foreach (var input in inputs)
            {
                BlockingCollection <T> .AddToAny(queues, input);
            }
            foreach (var queue in queues)
            {
                queue.CompleteAdding();
            }
            await Task.WhenAll(tasks).ConfigureAwait(false);
        }
        finally
        {
            foreach (var queue in queues)
            {
                queue.Dispose();
            }
        }
    }
            public void Run()
            {
                // Run while all the input BlockingCollection instances IsCompleted is false
                // and no cancellation was requested
                while ((!Input.All(inputBC => inputBC.IsCompleted)) &&
                       (!_token.IsCancellationRequested))
                {
                    TInput item;
                    int    i = BlockingCollection <TInput> .TryTakeFromAny(
                        Input, out item, TIMEOUT, _token);

                    if (i >= 0)
                    {
                        if (Output != null)
                        {
                            // Process the item
                            TOutput result = _processor(item);
                            // Add the result to any of the output collections
                            BlockingCollection <TOutput> .AddToAny(Output, result, _token);
                        }
                        else
                        {
                            // The code is running the last consumer
                            _outputProcessor(item);
                        }
                    }
                }
                if (Output != null)
                {
                    // All the BlockingCollection instances finished
                    foreach (var outputBC in Output)
                    {
                        outputBC.CompleteAdding();
                    }
                }
            }
Example #17
0
        public void MainTest()
        {
            var cts = new CancellationTokenSource();

            Task.Run(() =>
            {
                if (Console.ReadKey().KeyChar == 'C')
                {
                    cts.Cancel();
                }
            });
            var sourceArrays = new BlockingCollection <int> [CollectionsNumber];

            for (int i = 0; i < sourceArrays.Length; i++)
            {
                sourceArrays[i] = new BlockingCollection <int>(Count);
            }
            var filter1 = new PipelineWorker <int, decimal>(sourceArrays, (n) => Convert.ToDecimal(n * 0.97), cts.Token, "filter1");
            var filter2 = new PipelineWorker <decimal, string>(filter1.Output, (s) => string.Format("--{0}--", s), cts.Token, "filter2");
            var filter3 = new PipelineWorker <string, string>(filter2.Output, (s) => WriteLine($"The final result is {s} on thread id {Thread.CurrentThread.ManagedThreadId}"), cts.Token, "filter3");

            try
            {
                Parallel.Invoke(() =>
                {
                    Parallel.For(0, sourceArrays.Length * Count, (j, state) =>
                    {
                        if (cts.Token.IsCancellationRequested)
                        {
                            state.Stop();
                        }
                        int k = BlockingCollection <int> .AddToAny(sourceArrays, j);
                        if (k >= 0)
                        {
                            WriteLine($"added{j} to souce Data on thread id  {Thread.CurrentThread.ManagedThreadId}");
                            Thread.Sleep(TimeSpan.FromMilliseconds(100));
                        }
                    });
                    foreach (var arr in sourceArrays)
                    {
                        arr.CompleteAdding();
                    }
                },
                                () => filter1.Run(),
                                () => filter2.Run(),
                                () => filter3.Run()
                                );
            }
            catch (AggregateException ae)
            {
                foreach (var ex in ae.InnerExceptions)
                {
                    WriteLine(ex.Message + ex.StackTrace.ToString());
                }
            }
            if (cts.Token.IsCancellationRequested)
            {
                WriteLine($"Operation has been canceled! Press Enter to exit.");
            }
            else
            {
                WriteLine("Press Enter to exit.");
            }
            //Console.ReadLine();
        }
Example #18
0
 public void Dispatch(Http http)
 {
     BlockingCollection <Http> .AddToAny(_requestQueues, http);
 }
Example #19
0
        private static void Main()
        {
            // Создаем 2 блокирующие коллекции для передачи строк
            var bc1 = new BlockingCollection <string>();
            var bc2 = new BlockingCollection <string>();

            // Создаем другую блокирующую коллекцию, которая будет использоваться для передачи целых чисел
            var bc3 = new BlockingCollection <string>();

            // Создаем два массива блокирующих коллекций
            BlockingCollection <string>[] bcland2 = { bc1, bc2 };
            BlockingCollection <string>[] bcAll   = { bc1, bc2, bc3 };

            var tokenSource = new CancellationTokenSource();

            // Создаем первый набор производителей
            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        string message = string.Format("Message from task {0}", Task.CurrentId);
                        // Добавляем сообщение в одну из двух доступных коллекций
                        BlockingCollection <string> .AddToAny(bcland2, message, tokenSource.Token);
                        tokenSource.Token.WaitHandle.WaitOne(1000);
                    }
                }, tokenSource.Token);
            }

            // Создаем второй набор производителей
            for (int i = 0; i < 3; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        string warning = string.Format("Warning from task {0}", Task.CurrentId);
                        bc3.Add(warning, tokenSource.Token);
                        tokenSource.Token.WaitHandle.WaitOne(500);
                    }
                }, tokenSource.Token);
            }

            // Создаем потребителей
            for (int i = 0; i < 2; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        string item;
                        int bcid = BlockingCollection <string> .TakeFromAny(bcAll, out item, tokenSource.Token);
                        Console.WriteLine("From collection {0}: {1}", bcid, item);
                    }
                }, tokenSource.Token);
            }

            Console.WriteLine("Press enter to cancel tasks");
            Console.ReadLine();

            tokenSource.Cancel();

            Console.WriteLine("Press enter to finish");
            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            // create a pair of blocking collections
            // that will be used to pass strings
            BlockingCollection <string> bc1 = new BlockingCollection <string>();
            BlockingCollection <string> bc2 = new BlockingCollection <string>();

            // create another blocking collection
            // that will be used to pass ints
            BlockingCollection <string> bc3 = new BlockingCollection <string>();

            // create two arrays of the blocking collections
            BlockingCollection <string>[] bc1and2 = { bc1, bc2 };
            BlockingCollection <string>[] bcAll   = { bc1, bc2, bc3 };

            // create a cancellation token source
            CancellationTokenSource tokenSource = new CancellationTokenSource();


            // create the first set of producers
            for (int i = 0; i < 5; i++)
            {
                Task.Factory.StartNew(() => {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        // compose the message
                        string message
                            = String.Format("Message from task {0}", Task.CurrentId);
                        // add the message to either collection
                        BlockingCollection <string> .AddToAny(bc1and2,
                                                              message, tokenSource.Token);
                        // put the task to sleep
                        tokenSource.Token.WaitHandle.WaitOne(1000);
                    }
                }, tokenSource.Token);
            }

            // create the second set of producers
            for (int i = 0; i < 3; i++)
            {
                Task.Factory.StartNew(() => {
                    while (!tokenSource.IsCancellationRequested)
                    {
                        // compose the message
                        string warning
                            = String.Format("Warning from task {0}", Task.CurrentId);
                        // add the message to either collection
                        bc3.Add(warning, tokenSource.Token);
                        // put the task to sleep for 500ms
                        tokenSource.Token.WaitHandle.WaitOne(500);
                    }
                }, tokenSource.Token);
            }

            // create the consumers
            for (int i = 0; i < 2; i++)
            {
                Task consumer = Task.Factory.StartNew(() => {
                    string item;
                    while (!tokenSource.IsCancellationRequested)
                    {
                        // take an item from any collection
                        int bcid = BlockingCollection <string> .TakeFromAny(bcAll,
                                                                            out item, tokenSource.Token);
                        // write out the item to the console
                        Console.WriteLine("From collection {0}: {1}", bcid, item);
                    }
                }, tokenSource.Token);
            }

            // prompt the user to press enter
            Console.WriteLine("Press enter to cancel tasks");
            Console.ReadLine();
            // cancel the token
            tokenSource.Cancel();

            // wait for input before exiting
            Console.WriteLine("Press enter to finish");
            Console.ReadLine();
        }
        public void ReadAll(Func <int, Release, bool> processor)
        {
            TaskCreationOptions taskOptions = TaskCreationOptions.LongRunning;

            Task[] consumers = new Task[this.ThreadCount];
            for (int i = 0; i < consumers.Length; ++i)
            {
                consumers[i] = Task.Factory.StartNew(delegate(object state)
                {
                    int threadNumber = (int)state;
                    int count        = 0;
                    try
                    {
                        string[] stringBatch;
                        while (true)
                        {
                            BlockingCollection <string[]> .TakeFromAny(stringCollection, out stringBatch, cancellationToken);
                            foreach (string releaseStringOriginal in stringBatch)
                            {
                                // Remove <releases>...</releases>
                                string releaseString = Utility.TrimString(releaseStringOriginal, "<releases>");
                                releaseString        = Utility.TrimString(releaseString, "</releases>");

                                var fixedText = Utility.FixXmlText(releaseString);
                                XDocument doc = XDocument.Parse(fixedText);
                                var release   = DataReader.ReadRelease(doc.Root);
                                ++count;
                                if (!processor(threadNumber, release))
                                {
                                    cancellationSource.Cancel();
                                    throw new OperationCanceledException();
                                }
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    catch (InvalidOperationException)
                    {
                    }
                    catch (ArgumentException)
                    {
                    }
                }, i, taskOptions);
            }
            Task stringProducer = Task.Factory.StartNew(delegate
            {
                try
                {
                    string[] stringBatch;
                    while (ReadBatch(BatchSize, out stringBatch))
                    {
                        BlockingCollection <string[]> .AddToAny(stringCollection, stringBatch, cancellationToken);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (InvalidOperationException)
                {
                }
                finally
                {
                    foreach (var coll in stringCollection)
                    {
                        coll.CompleteAdding();
                    }
                }
            }, taskOptions);
            Task dataReader = Task.Factory.StartNew(delegate
            {
                try
                {
                    int read         = 0;
                    char[] NewBuffer = new char[BufferSize];
                    while ((read = reader.ReadBlock(NewBuffer, 0, BufferSize)) > 0)
                    {
                        bufferCollection.Add(new CharBuffer(NewBuffer, read), cancellationToken);
                        NewBuffer = new char[BufferSize];
                    }
                }
                catch (OperationCanceledException)
                {
                }
                finally
                {
                    bufferCollection.CompleteAdding();
                }
            }, taskOptions);

            Task.WaitAll(consumers);
            stringProducer.Wait();
            dataReader.Wait();
        }