Beispiel #1
0
            public void Start()
            {
                if (m_to != null)
                {
                    m_to.AddProducer();
                }

                // While there are elements available, read from one and write to
                // the other
                try
                {
                    while (true)
                    {
                        try
                        {
                            object workToDo = null;

                            if (m_numItems == 1 && m_toWait == INFINITE)
                            {
                                workToDo = m_from.Remove();
                            }
                            else
                            {
                                workToDo = m_from.Remove(m_numItems, m_toWait, true);
                            }

                            // Random sleep time to simulate work
                            Thread.Sleep(m_rand.Next(1, 5));

                            if (!(workToDo is ICollection))
                            {
                                // Increment the number processed
                                Interlocked.Increment(ref NumProcessed);

                                // Add this to the next queue
                                if (m_to != null)
                                {
                                    m_to.Add(workToDo);
                                }
                            }
                            else
                            {
//								foreach( object work in (ICollection)workToDo )
//								{
//									// Increment the number processed
//									Interlocked.Increment( ref NumProcessed ) ;
//								}

                                NumProcessed += ((ICollection)workToDo).Count;

                                // Add these to the next queue
                                foreach (object work in (ICollection)workToDo)
                                {
                                    if (m_to != null)
                                    {
                                        while (!m_to.Add(work, m_toWait))
                                        {
                                            Thread.Sleep(23);
                                        }
                                    }

                                    // Random sleep time to simulate work
                                    Thread.Sleep(m_rand.Next(1, 5));
                                }
                            }
                        }
                        catch (NoMoreException)
                        {
                            break;                              // No more elements were available
                        }
                    }
                }
                finally
                {
                    // Remove the producer relationships

                    if (m_to != null)
                    {
                        m_to.RemoveProducer();
                    }

                    if (m_from != null)
                    {
                        m_from.RemoveProducer();
                    }
                }
            }
Beispiel #2
0
//		public static void Main( string[] args )
//		{
//
//			if ( args != null && args.Length > 0 )
//			{
//				foreach( string arg in args )
//				{
//					switch( arg )
//					{
//
//						case "-unittest":
//							//
//							// Unit test
//							//
//							Environment.Exit( ThreadQueue.UnitTest() ) ;
//							break ;
//
//						default:
//							Console.WriteLine("Error: unknown argument {0}", arg ) ;
//							break ;
//					}
//				}
//			}
//		}

        public static int UnitTest()
        {
            // Generic item to produce random values
            Random rand = new Random();

            string testDescription =
                string.Format(
                    "***\n" +
                    "*** Unit test to ensure that an item only comes off of the queue once, not\n" +
                    "*** multiple times for each Remove() operation\n" +
                    "***\n");

            Console.WriteLine(testDescription);

            ArrayList   allThreads = new ArrayList();
            ArrayList   consumers  = new ArrayList();
            ThreadQueue startQueue = new ThreadQueue();
            ThreadQueue feedQueue  = new ThreadQueue();

            feedQueue.HighWater       = rand.Next(11, 250);
            feedQueue.LowWater        = rand.Next(1, feedQueue.HighWater);
            feedQueue.EnableHighWater = true;

            // Create a queue, and start running against it
            for (int i = 0; i < rand.Next(7, 23); i++)
            {
                UnitTestThread feeder =
                    new UnitTestThread(startQueue, feedQueue, new TimeSpan(Timeout.Infinite), rand.Next(1, 100));

                Thread feederThread = new Thread(new ThreadStart(feeder.Start));
                feederThread.Name = string.Format("Feeder {0}", i);

                feedQueue.AddProducer(feederThread);

                allThreads.Add(feederThread);
            }

            for (int i = 0; i < rand.Next(2, 7); i++)
            {
                // Note:, the first thread will always do one item at a time
                int numItems = i == 0 ?
                               1 :
                               rand.Next(2, 23);

                TimeSpan toWait = i == 0 ?
                                  new TimeSpan(Timeout.Infinite) :
                                  new TimeSpan(0, 0, 0, 0, rand.Next(10, 10 * 1000));

                UnitTestThread consumer =
                    new UnitTestThread(feedQueue, null, toWait, numItems);

                Thread consumerThread = new Thread(new ThreadStart(consumer.Start));
                consumerThread.Name =
                    string.Format("Consumer: {0}, numPerCall: {1}, toWait: {2}", i, numItems, toWait);

                consumers.Add(consumer);
                allThreads.Add(consumerThread);
            }


            // Queue up some items
            int totalItems = rand.Next(10 * 1000, 20 * 1000);

            Console.WriteLine("Total items to process: {0}", totalItems);
            for (int i = 0; i < totalItems; i++)
            {
                startQueue.Add(i, false);
            }

            foreach (Thread thd in allThreads)
            {
                Console.WriteLine("Starting thread: {0}...", thd.Name);
                thd.Start();
            }

            // Wait for all the threads to finish

            bool isAlive = false;

            do
            {
                Console.WriteLine(
                    "StartQueue: {0} items, FeedQueue: {1} (LowWater: {2}, HighWater: {3})",
                    startQueue.Count,
                    feedQueue.Count,
                    feedQueue.LowWater,
                    feedQueue.HighWater);

                isAlive = false;

                foreach (Thread thd in allThreads)
                {
                    isAlive |= thd.IsAlive;

                    if (isAlive)
                    {
                        break;
                    }
                }

                if (isAlive)
                {
                    Thread.Sleep(2 * 1000);
                }
            }while(isAlive);

            Console.WriteLine(
                "*Finished: StartQueue: {0} items, FeedQueue: {1}", startQueue.Count, feedQueue.Count);

            Console.WriteLine("Consumer counts: ");

            long consumerCount = 0;

            foreach (UnitTestThread consumer in consumers)
            {
                Console.WriteLine("\t{0} items", consumer.NumProcessed);

                consumerCount += consumer.NumProcessed;
            }

            if (consumerCount != totalItems)
            {
                Console.WriteLine("***\n" +
                                  "*** Failed test, consumers consumed {0} of {1} items\n" +
                                  "***\n",
                                  consumerCount, totalItems);
            }
            else
            {
                Console.WriteLine("***\n" +
                                  "*** Passed test, consumers consumed {0} of {1} items\n" +
                                  "***\n",
                                  consumerCount, totalItems);
            }

            //
            // Unit test for items flowing from one Queue to another to make sure all the
            // items get from the head to the tail
            //


            // Create several queues to shuffle the objects along
            ThreadQueue[] queues = new ThreadQueue[rand.Next(5, 15)];
            for (int i = 0; i < queues.Length; i++)
            {
                queues[i] = new ThreadQueue();
            }

            Console.WriteLine("* Created {0} queues", queues.Length);

            // Prime the first queue with some objects
            totalItems = rand.Next(10, 20000);
            for (int i = 0; i < totalItems; i++)
            {
                queues[0].Add(rand.Next(-10000, -1000).ToString(), false);
            }

            Console.WriteLine("* Primed the first queue with {0} items",
                              totalItems);

            ArrayList allThds = new ArrayList();

            Console.Write("* Threads per queue (queue number: thread count):\n*");

            // Setup threads to read from the queues and write to the next queue
            for (int i = 0; i < queues.Length - 1; i++)
            {
                int numThds;

                // Create at a minimum of threads reading from each queue
                for (numThds = 0; numThds < rand.Next(5, 30); numThds++)
                {
                    ThreadQueue    fromQueue = queues[i];
                    ThreadQueue    toQueue   = (i == queues.Length) ? null : queues[i + 1];
                    UnitTestThread test      = new UnitTestThread(fromQueue, toQueue);

                    // Create the thread
                    Thread thd = new Thread(new ThreadStart(test.Start));
                    thd.Name = String.Format("{0} -> {1}", i, i + 1);

                    if (i == 1)
                    {
                        // Make this thread a producer of itself
                        fromQueue.AddProducer(thd);
                    }

                    // Set the thread as a producer for the next queue
                    toQueue.AddProducer(thd);


                    allThds.Add(thd);
                }

//					// Add one loop that continually takes and item from it's queue and
//					// places it back up the stream some where
//
//					int  earlier	= rand.Next( 0, i - 1 ) ;
//					readFromOwn = new UnitTestThread( queues[i], queues[i+1], queues[ earlier ] );
//					loop		= new Thread( new ThreadStart(readFromOwn.Start ) ) ;
//					loop.Name	= String.Format("{0} -> {1}", i, earlier ) ;
//					allThds.Add( loop ) ;
//
//					numThds++ ;


                Console.Write(" {0}:{1},", i, numThds);
            }

            Console.WriteLine("");

            // Disable the high water on the last queue
            queues[queues.Length - 1].EnableHighWater = false;

            // Start all the threads
            foreach (Thread thd in allThds)
            {
                thd.Start();
            }

            DateTime endTime = DateTime.Now + new TimeSpan(0, 10, 0);

            // Wait for all of the elements to end up in the last queue
            while (queues[queues.Length - 1].Count < totalItems &&
                   DateTime.Now < endTime)
            {
                Thread.Sleep(5000);
                Console.WriteLine("* {0} of {1} items have arrived in the final queue (#{2})",
                                  queues[queues.Length - 1].Count,
                                  totalItems,
                                  queues.Length - 1);
            }

            int waitingThreads = 0;

            // Kill all of the threads
            foreach (Thread thd in allThds)
            {
                thd.Join(new TimeSpan(0, 0, 5));
                if (thd.IsAlive)
                {
                    if ((thd.ThreadState & System.Threading.ThreadState.WaitSleepJoin) != 0)
                    {
                        waitingThreads++;
                    }
                    thd.Abort();
                }
            }

            int itemsProcessed = queues[queues.Length - 1].Count;

            if (itemsProcessed != totalItems || waitingThreads != 0)
            {
                Console.WriteLine("* Failed test, only {0} of {1} items were processed " +
                                  " and {2} of {3} threads were waiting",
                                  itemsProcessed, totalItems, waitingThreads, allThds.Count);
            }
            else
            {
                Console.WriteLine("* Passed test, final queue has {0} of {1} items, " +
                                  "{2} of {3} threads were waiting",
                                  itemsProcessed,
                                  totalItems,
                                  waitingThreads,
                                  allThds.Count);
            }

            int toReturn = (itemsProcessed == totalItems) ? 0 : -1;

            return(toReturn);
        }