Search code examples
c#multithreadingdelegatespdc

Parallel Computing in C# Two classes printer and Load balance , load balance class contains 2 printers i.e hp101 and hp434


I ran into a problem called parallel computing.

I have two classes, Load Balance and Printer.

The printer class contains lock to prevent another printer came across now the load balancer class has all printers it is his duty to manage printers to save time

namespace Printer
{
    public   class printer
    {
        public static string Name;
        //constructor  printer getting name of printer
        public printer(string name) => Name = name;

        public  void print(int pages)
        {
            // this method is printing current requested page   in given printer
            lock (this)
            {
                Task .Run(() =>
                {
                    for (int i = 0; i < pages; i++)
                    {
                        Console. WriteLine($"printing page {i}  in printer {Name}");
                        Thread. Sleep(300);
                    }
                });
            }
        } 
    }

    public class Loadbalancer
    {
        // This class contains request came across main function  and then it uses algorithm and decides to whom the request 
        // should be sent. This algorithm checks which printer has fewer pages 
        // so it should take less time 
        int page;
      
        List<int> pages = new List<int>();

        public Loadbalancer (int page)
        {
            int TotalPagesToP1 = 0;
            int TotalPagesToP2 = 0;

            // printer print  = new printer(Printer);
            printer p1 = new printer("HP 1222");
            printer p2 = new printer("HP 1434");
            pages.Add(page);

            int currentIndex = 0;

            for (; currentIndex < pages.Count; currentIndex++) 
            {
                if(TotalPagesToP1 < TotalPagesToP2)
                {
                    p1.print(pages[currentIndex]);
                    TotalPagesToP1 += pages[currentIndex];
                }
                else
                {
                    p2.print(pages[currentIndex]);
                    TotalPagesToP2 += pages[currentIndex];
                }
            }
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            // these are the page request to  be printed which is sent to centralized load balancer class it
            // it will decide to whom these page request should be sent 
            Task.Run(() =>
            {
                Loadbalancer k = new Loadbalancer(10);
                Loadbalancer b = new Loadbalancer(20);
                Loadbalancer c = new Loadbalancer(30);
            });

            Console.ReadKey();
        }
    }
}

The problem: printer now simulating only printer HP 434 is in action while HP101 is relaxed

I tried if else conditions

if ( printer 1 has less pages  the printer 2 ) 
then  give  pages to printer 1 
else printer 2   

to synchronize


Solution

  • You've declared the printer name as a static variable. This means there is one name for all printers. Every time you create a new printer, you are overwriting the name.


    Instead of telling the printers what they need to print, I would suggest making a print queue, and letting the printers ask for more work when they are idle.

    public class PrintJob
    {
        public int Pages { get; private set; }
    
        public PrintJob(int pages) => Pages = pages;
    }
    
    public class PrintQueue
    {
        public void AddJob(PrintJob job)
        {
            // Add a job to the queue
            // Signal any waiting threads
        }
    
        public PrintJob GetJob()
        {
            // Get the first job from the queue
            // While the queue is empty, wait for a signal
        }
    }
    
    public class Printer
    {
        public string Name { get; private set; }
        public PrintQueue Queue { get; private set; }
    
        public Printer(string name, PrintQueue queue)
        {
            Name = name;
            Queue = queue;
            // Start the printer here, or provide an explicit 'Start' method
        }
    
        private void Run()
        {
            while (true)
            {
                var job = Queue.GetJob();
                if (job == null)
                {
                    // If the queue returns null, it has been closed
                    // This allows you to exit the program gracefully
                    return;
                }
    
                Print(job);
            }
        }
    
        private void Print(PrintJob job)
        {
            for (int i = 0; i < job.Pages; i++)
            {
                Console.WriteLine("Printing page {0} in printer {1}", i, Name);
                Thread.Sleep(300);
            }
        }
    }
    

    I would also strongly recommend you use Task and async/await methods for this. Currently, each printer hogs a whole thread even when it is idle.