예제 #1
0
 public Consumer(string id, PCQueue pcQueue, LocationList constituencyList, ProgressManager progManager)
 {
     this.id               = id;
     finished              = false; // Initially not finished
     this.pcQueue          = pcQueue;
     this.constituencyList = constituencyList;
     this.progManager      = progManager;
     (T = new Thread(run)).Start(); // Create a new thread for this consumer and get it started
     RunningThreads++;              // Increment the number of running consumer threads;
 }
예제 #2
0
        public void RunProducerConsumer()
        {
            //Create cyclist list to hold individual cyclist objects read from datasets
            locList = new LocationList();

            // Create progress manager with number of files to process
            ProgressManager progManager = new ProgressManager(configData.configRecords.Count);

            // Output message to indicate that the program has started
            progressLbl.Text = "Creating and starting all producers and consumers";

            // Create a PCQueue instance, give it a capacity of 4
            var pcQueue = new PCQueue(4);

            // Create 2 Producer instances and 2 Consumer instances, these will begin executing on
            // their respective threads as soon as they are instantiated
            Producer[] producers = { new Producer("P1", pcQueue, configData, IOhandler),
                                     new Producer("P2", pcQueue, configData, IOhandler) };

            Consumer[] consumers = { new Consumer("C1", pcQueue, locList, progManager),
                                     new Consumer("C2", pcQueue, locList, progManager) };

            // Keep producing and consuming until all work items are completed
            while (progManager.ItemsRemaining > 0)
            {
                ;
            }

            // Output message to indicate that the program is shutting down
            progressLbl.Text = "Shutting down all producers and consumers";

            // Deactivate the PCQueue so it does not prevent waiting producer and/or consumer threads
            // from completing
            pcQueue.Active = false;

            // Iterate through producers and signal them to finish
            foreach (var p in producers)
            {
                p.Finished = true;
            }

            // Iterate through consumers and signal them to finish
            foreach (var c in consumers)
            {
                c.Finished = true;
            }

            // We need to ensure that no thread waiting on Monitor.Wait() is stranded with
            // no Monitor.Pulse() now possible since all producer and consumer threads have
            // been signalled to stop, in the worse case all such threads could be stranded
            // so pulse that many times to ensure enough pulses are made available (or the
            // program can halt erroneously), wasted pulse are simply ignored
            for (int i = 0; i < (Producer.RunningThreads + Consumer.RunningThreads); i++)
            {
                lock (pcQueue)
                {
                    // Pulse the PCQueue to signal any waiting threads
                    Monitor.Pulse(pcQueue);

                    // Give a short break to the main thread so the pulses have time to be
                    // detected by any potentially waiting producer and/or consumer threads
                    Thread.Sleep(100);
                }
            }

            // Once all producer and consumer threads have finally finished we can gracefully
            // shutdown the main thread, this is achieved by spinning on a while() loop until
            // there are no running threads, in this case we do not mind the main thread
            // spinning as we are about to shutdown the program
            while ((Producer.RunningThreads > 0) || (Consumer.RunningThreads > 0))
            {
                ;                                                                    // Wait by spinning
            }
            Console.WriteLine();
            progressLbl.Text = "All producers and consumers shut down";
        }