Click here to Skip to main content
15,886,035 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
Hello guys
I am developing a multi-threading application using C# and VS 2010 but I am getting a error that semaphore full exception was unhandled "adding the specified count to the semaphore would cause it to exceed its maximum count". Please have a look at it

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using chickenFarm.Encrypt;
using System.Diagnostics;

namespace chickenFarm
{
    public delegate void priceCutter(Int32 pr);

    class EncoderDecoder
    {
        public string encode(OrderClass order)
        {
            //int id = order.getID();
            //int card = order.getCardNo();
           // int amt = order.getAmt();
            Console.WriteLine("Encoding the order {0}:{1}:{2}", order.getID(), order.getCardNo(), order.getAmt());
            return order.getID() + "6" + order.getCardNo() + "6" + order.getAmt() + "6";
            
        }

        public OrderClass decode(string order)
        {
            string[] Split = order.Split( '6' );
            OrderClass oc = new OrderClass();
            oc.setID(Int32.Parse(Split[0]));
            oc.setCardNo(Int32.Parse(Split[1]));
            oc.setAmt(Int32.Parse(Split[2]));
            Console.WriteLine("Decoding the order {0}:{1}:{2}", oc.getID(), oc.getCardNo(), oc.getAmt());
            return oc;
        }
    }//end EncoderDecoder

       class ChickenFarm
       {
           static Random r = new Random();
           Retailer retail;
           static MultiCellBuffer mcb;
           public static event priceCutter priceCut; // Define event
           private static int chickenPrice = 4;
           private static int p;

           public ChickenFarm()
           { }
          

           public ChickenFarm(Retailer r, MultiCellBuffer m)
           {
               retail = r;
               mcb = m;
               openFarm();
           }

           public int getPrice()
           {
               return chickenPrice;
           }

           public void openFarm()
           {
               retail.openFarm();
           }


           public void PricingModel()
           {
               Stopwatch watch = new Stopwatch(); // for time elapsed
               DateTime time = new DateTime();
               time = DateTime.Now;
               string format = "HH:mm:ss";

               Console.WriteLine("Chicken farm is open! Start time: " + time.ToString(format));
               watch.Start();
               int price;
               while (p <= 10)
               {
                   Thread.Sleep(2000); //price is updated every 2 seconds 
                   price = r.Next(4, 10);
                   Console.WriteLine("Current price is ${0:N}", chickenPrice);
                   changePrice(price);
               }
               watch.Stop();
               retail.openFarm();
               Thread.Sleep(3000);
               Console.WriteLine("The Chicken farm has closed! Elapsed time: {0}", watch.Elapsed);
               Console.WriteLine("Press any key to quit");
               Console.ReadLine();
           }

           public static void changePrice(int price)
           {
               if (price < chickenPrice)
               {
                   if (priceCut != null)
                   {
                       Console.WriteLine("\n******Price Cut!******\n");
                       priceCut(price); // emit event to subscribers
                       p++;
                   }
               }
               chickenPrice = price;
           }

           public string processOrder(int cell) //sends an order to the Order Processing class.
           {
               Encrypt.ServiceClient myClient = new Encrypt.ServiceClient();
               string ord;
               ord = mcb.getOneCell(cell);
               EncoderDecoder ed = new EncoderDecoder();
               OrderProcessing op = new OrderProcessing(ed.decode(ord), chickenPrice);

               Thread order = new Thread(new ThreadStart(op.process));
               order.Start();
               while (order.IsAlive)
               {
                   Thread.Sleep(50);
               }
               return op.printOrder();
           }

         /*  public priceCutter priceCutter
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

           internal MultiCellBuffer MultiCellBuffer
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

           internal OrderProcessing OrderProcessing
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

           internal EncoderDecoder EncoderDecoder
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

           internal Retailer Retailer
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }
           */
       }

    
       class MultiCellBuffer
       {
           private int maxCells = 0;
           private string[] cells;
           private Semaphore sem;


           public MultiCellBuffer(int n)
           {
               maxCells = n;
               // Console.WriteLine("New Price is {0}", n);
               cells = new string[n];
               for (int i = 0; i < n; i++)
               {
                   cells[i] = "";
                   //Console.WriteLine("New Price is {0}", cells[i]);
               }
               sem = new Semaphore(n, n);
               // Console.WriteLine("New Price is {0}", sem);
           }

           public string setOneCell(string s)
           {
               sem.WaitOne();
               int cell = -1;
               string result;
               lock (cells) //locks cell array for empty cell searching
               {
                   for (int i = 0; i < maxCells; i++)
                   {
                       if (cells[i] == "")
                           cell = i;
                   }

                   if (cell != -1)
                   {
                       cells[cell] = s;
                   }
                   else
                   {
                       Console.WriteLine("Error. No empty cells found.");
                   }
               }
               ChickenFarm c = new ChickenFarm();
               result = c.processOrder(cell); //upon finding writing to a cell, the farm is called to get the order.
               cells[cell] = "";
               sem.Release(); // cell is emptied and made available
               return result;
           }

           public string getOneCell(int cellNo)
           {
               return cells[cellNo];
           }
       }

       class Retailer
       {
           bool farmOpen = false;
           static int threadCount, turnstile = 0;
           Random r = new Random();
           MultiCellBuffer mcb;
           Semaphore retailSem1, retailSem2;

           public Retailer(MultiCellBuffer m, int n)
           {
               //Console.WriteLine("New Price is {0}", n);
               mcb = m;
               threadCount = n;
               retailSem1 = new Semaphore(0, n);
               retailSem2 = new Semaphore(0, n);
           }

        /*   internal MultiCellBuffer MultiCellBuffer
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

           internal OrderClass OrderClass
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }

          /* internal EncoderDecoder EncoderDecoder
           {
               get
               {
                   throw new System.NotImplementedException();
               }
               set
               {
               }
           }
           */
           
           public void startRetail()  //for starting retailer threads  
           {
               OrderClass order = new OrderClass(); //Each thread receives their own "Order Form"
               EncoderDecoder ed = new EncoderDecoder(); //Each thread receives its own Encoder, simulating an independent client-side operation
               int amt = r.Next(10, 50);
               string finalOrder, callback;
               DateTime time = new DateTime();
               string format = "HH:mm:ss";
               Stopwatch watch = new Stopwatch(); //uses a Stopwatch for elapsed time

               while (farmOpen == true)
               {
                   retailSem1.WaitOne(); ////////////////////////////////////////////////////////////////////////////////////////////
                   turnstile += 1;
                   if (turnstile == threadCount)
                   {
                       turnstile = 0;
                       retailSem2.Release(threadCount);//This block uses a double turnstile technique to prevent concurrency issues.
                   }                                   // Though it still seems to have issues every now and then...
                   retailSem2.WaitOne();/////////////////////////////////////////////////////////////////////////////////////////////

                   time = DateTime.Now;
                   watch.Start();
                   order.setID(Convert.ToInt32(Thread.CurrentThread.Name)); //create new order
                   order.setAmt(r.Next(10, 60));
                   order.setCardNo(r.Next(2000, 4000));

                   finalOrder = ed.encode(order); // encode order
                   time = DateTime.Now; // for timestamp
                   Console.WriteLine("Retailer {0} has placed an order for {1} chickens." + time.ToString(format), Thread.CurrentThread.Name, amt);
                   callback = mcb.setOneCell(finalOrder); // place order and receive confirmation.
                   watch.Stop();
                   Console.WriteLine(callback + "\n" + watch.Elapsed);
               }
           }

           public void chickenOnSale(int p)
           {  // Event handler
               Console.WriteLine("Chickens are on sale for ${0:N}.\n", p);
               retailSem1.Release(threadCount);

           }

           public void openFarm()
           {
               if (farmOpen == true)
                   farmOpen = false;
               else
                   farmOpen = true;
           }

       }//end Retailer

       class OrderClass
       {
           private int senderID, cardNo, amount;

           public void setID(int id)
           {
               senderID = id;
           }

           public int getID()
           {
               return senderID;
           }

           public void setCardNo(int num)
           {
               cardNo = num;
           }

           public int getCardNo()
           {
               return cardNo;
           }

           public void setAmt(int amt)
           {
               amount = amt;
           }

           public int getAmt()
           {
               return amount;
           }

           public string toString()
           {
               return ("Retailer: " + senderID + " Card Number: " + cardNo + " Amount: " + amount);
           }


       }//end OrderClass

       class OrderProcessing
       {
           private int amount, cardNo, ID, price;
           private double total, shipping = 5.99;
           private string OrderStatus = "Awaiting Processing";

           public OrderProcessing(OrderClass oc, int p)
           {
               amount = oc.getAmt();
               cardNo = oc.getCardNo();
               ID = oc.getID();
               price = p;
           }

           public void process()
           { //checks card number and calculates total price for the order. Sets confirmation string.
               if (checkCardNo())
               {
                   double tax = (amount * price) * .097;
                   total = (amount * price) + tax + shipping;
                   OrderStatus = ("Retailer " + ID + ": order processed. Total for " + amount + " chicken(s) at " + price.ToString("C") + " was " + total.ToString("C") + ".");
               }
               else
                   OrderStatus = ("Retailer" + ID + ": Order could not be processed. Invalid card number.");

           }

           public bool checkCardNo()
           {
               if (cardNo >= 2000 && cardNo <= 4000)
                   return true;
               else
                   return false;
           }

           public string printOrder()
           { //Sends confirmation string upon request.
               return OrderStatus;
           }
       }

      public class myApplication 
      {
          private const int retailerNum = 10; //Number of retailers
          private const int multiCellNum = 8;

     static void Main(string[] args) 
     {
         MultiCellBuffer mcb = new MultiCellBuffer(multiCellNum);//=4
         Retailer retail = new Retailer(mcb, retailerNum);//=(value from mcb,10)
         ChickenFarm chicken = new ChickenFarm(retail, mcb);

         ChickenFarm.priceCut += new priceCutter(retail.chickenOnSale);

         Thread farm = new Thread(new ThreadStart(chicken.PricingModel));
         farm.Start(); //Single farm thread. 

         Thread[] retailers = new Thread[retailerNum];
         for (int i = 0; i < retailerNum; i++)
         {   // Start N retailer threads
             retailers[i] = new Thread(new ThreadStart(retail.startRetail));
             retailers[i].Name = (i + 1).ToString();
             retailers[i].Start();
         }
     }
  }

}


I tried many ways to solve it but I think i cant figure it out.Thanks in advance
Posted
Comments
Sergey Alexandrovich Kryukov 9-Feb-14 23:38pm    
In what line?
What is the purpose of using the semaphore?
—SA
Sergey Alexandrovich Kryukov 9-Feb-14 23:50pm    
It is already irrelevant. The whole thing looks pointless. Please see my answer...
—SA

This is not a good question, just because you just show a code dump, not explaining anything. Normally, you need to explain the goals of your work first and provide not the real code, but some simple code focusing only on the problem you are looking for help about. If the behavior of your code does not match what you expected, use the debugger and fix it. If you failed to do so, describe what did you want to achieve, what's expected behavior, what is observed behavior, why do you feel it's wrong. If you have some exceptions, describe steps to reproduce, complete exception information. Comment the points in code related to exception throwing/propagation. Post all what's relevant. See also: http://www.sscce.org.

At the same time, the fair rules of code reviews and providing some help allows to read it until the first big problem is encountered. I tried to scan your code with my eyes until I stopped on these two fragments of the code:
C#
while (order.IsAlive)
{
    Thread.Sleep(50);
}
and
C#
while (p <= 10)
    {
        Thread.Sleep(2000);
        //...
    }

Both pieces are related to something called "spin wait", which is a really bad thing. And tells me, that, despite of using the semaphores somewhere else, are not really using threading and thread synchronization at all. These fragment of code makes further reading useless: they already tells me that your general design of code is wrong and is not worth considering.

I cannot tell you what would you need to do instead, because you never explained the purpose of these fragments, and pretty much nothing about your code at all. Let me tell you one key consideration. Let's say, you write Thread.Sleep(50). My question would be: why not 51? I am sure you cannot provide satisfactory answer. It means that the whole idea is wrong. This is not how multithreading is applied for solving application problems.

—SA
 
Share this answer
 
v2
Abhinav_007 wrote

I'm sorry for not providing a full explanation. Here is what I was trying to achieve in my project:
(1) The ChickenFarm uses a pricing model to calculate the chicken price. If the new price is lower than the previous price, it emits an event and calls the event handlers in the retailers that have subscribed to the event.
(2) A Retailer evaluates the price, generates an OrderObject (consisting of multiple values), and sends the order to the Encoder to convert the order object into a plain string.
(3) The Encoder converts the object into a string.
(4) The Encoder sends the encoded string back to the caller.
(5) The Retailer sends the encoded string to one of the free cells in the MultiCellBuffer.
(6) The ChickenFarm receives the encoded string from the MultiCellBuffer and sends the string to the Decoder for decoding.
(7) The Decoder sends the OrderObject to the ChickenFarm. The decoded object must contain the same values generated by the Retailer.
(8) The ChickenFarm creates a new thread to process the order;
(9) The OrderProcessingThread processes the order, e.g., checks the credit card number and calculates the amount.
(10) The OrderProcessingThread sends a confirmation to the retailer and prints the order.

Now, the chickenOnSale(int p) method inside Retailer class is printing the Chicken price and then releasing the no. of retailers or threadcount which is 8 in this case. But I'm not able to figure out what is causing the semaphore exception.When I run the program, it executes for sometime and then semaphore exception is encountered. Please have a look again and give your inputs SA.
This is my feedback:

(1) Event is not "emitted", it is invoked. The term "emit" is reserved for generation of the code directly in memory, see System.Reflection.Emit.

(2) I don't know what exactly do you mean by "plain string", but I would strongly advise not to invent your own string-based format; base it on XML or JSON.

(3) This is called "serialization" and cannot be called "convert. Use some standard serialization, preferably Data Contract. Please see:

(4) Why sending anything back?!

(5-7) ... It looks way to convoluted/redundant.

(8) This leads to uncontrolled creation of threads. Reasonable architecture should rather use fixed number of thread (perhaps desided after reading some configuration), and, on the task of procesing some order, the orders should be queues and threads reused.

(9) The problems of exchange of the card information is not appropriately considered. This is a very serious security item, more important than all of the above.

(10) Nothing should be directly printed. The customer should get a printable message and decide what to print and what not.

You never indicated how it can be possibly related to the semaphore and what is the semaphore problem. I seems to me that you are not aware of real use of semaphores. From what I can see no, the regular lock statements would suffice.

Overall, I have an impression that you are not yet prepared for this project. Your architecture is not developed to the level close to the point where you can start implementation. Instead of trying to implement the whole scenario, you should probably try to prototype some techniques on separate prototype projects. Even in this case, I am not sure if you have enough skills for that. At least try to proceed very cautiously and not try to put all things together at once.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900