C# endless list is filled and taken - BlockingCollection

Markus Freitag 3,786 Reputation points
2020-12-17T15:24:04.207+00:00

Hello,
I have a thread that receives data and buffers it in a list. Another thread that takes this data.

Task t1 = Task.Run(() =>  
                {  
                    bc.Add(1);  
                    bc.Add(2);  
                    bc.Add(3);  
                    bc.Add(4);  
                    bc.CompleteAdding();  
                });  
  

This is endless, I don't know when it will be completed. I can't call bc.CompleteAdding();

I am looking for a good example to solve this requirement. Can you please help me with an example? Thank you in advance.

the block diagram

49140-fill-and-take.png

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
0 comments No comments
{count} votes

Accepted answer
  1. YASER SHADMEHR 781 Reputation points
    2020-12-17T17:23:46.667+00:00

    Your scenario like ConcerentQueue without bounding. So you don't need to use CompleteAdding:

    // Initialize Q and Cancelleation Token
    var q = new BlockingCollection<int>();
    var cts = new CancellationTokenSource();
    var ct = cts.Token;
    
    // Producer Thread.
    var t1 = Task.Run(() =>
    {
        int i = 0;
        do
        {
            q.Add(++i);
            Console.WriteLine(i + " is added to q");
        }
        while (!ct.IsCancellationRequested);
        Console.WriteLine("producer task is canceled");
    }, ct);
    
    // Consumer Thread.
    var t2 = Task.Run(() =>
    {
        do
        {
            while(q.Count > 0)
            {
                var result = q.Take();
                Console.WriteLine(result + " is removed from q");
            }
        }
        while (!ct.IsCancellationRequested);
        Console.WriteLine("consumer task is canceled");
    }, ct);
    

    To see in action, create a console app and copy the above code in the main function:

    using System;
    using System.Threading;
    using System.Collections.Concurrent;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Copy above code here
    
                Console.Title = "Press any key to exit";
                Console.ReadLine();
    
                Console.Title = "Wait to Queue get empty";
    
                // Cancel t1 & t2
                cts.Cancel();
    
                // Wait for both thread to done
                Task.WaitAll(t1, t2);
            }
        }
    }
    

    See this example for using CompleteAdding.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful