コード例 #1
0
        private ConcurrentLinkedList <BOX <long> > CreateProducersConsumers(int countEntries,
                                                                            int TailProducers,
                                                                            int TailConsumers,
                                                                            int HeadProducers,
                                                                            int HeadConsumers,
                                                                            int MaxProducerRandomDelay,
                                                                            int MaxConsumersRandomDelay,
                                                                            int InitialConsumerDelay = 10)
        {
            var currentEntry  = 0;
            var totalProduced = 0;
            var totalConsumed = 0;
            var LL            = new ConcurrentLinkedList <BOX <long> >();
            var rnd           = new Random();

            List <Task <int> > consumerTasks = new List <Task <int> >();
            List <Task <int> > producerTasks = new List <Task <int> >();


            Func <bool, string, Task <int> > producer = async(bIsTail, producerId) =>
            {
                var produced = 0;
                Trace.WriteLine(string.Format("Producer {0} is {1}", producerId, bIsTail ? "Tail" : "Head"));


                while (Interlocked.Increment(ref currentEntry) <= countEntries)
                {
                    produced++;
                    var newVal = DateTime.UtcNow.Ticks;
                    Trace.WriteLine(string.Format("Producer {0} + {1}", producerId, newVal));

                    if (bIsTail)
                    {
                        LL.AddTail(new BOX <long>(newVal));
                    }
                    else
                    {
                        LL.AddHead(new BOX <long>(newVal));
                    }


                    await Task.Delay(rnd.Next(0, MaxProducerRandomDelay));
                }
                return(produced);
            };


            Func <bool, string, Task <int> > consumer = async(bIsTail, consumerId) =>
            {
                // all consumer wait a bit this almost elminate the need for that CX below
                await Task.Delay(InitialConsumerDelay); //

                Trace.WriteLine(string.Format("Consumer {0} is {1}", consumerId, bIsTail ?  "Tail" : "Head"));
                var        consumed = 0;
                BOX <long> node;
                while ((bIsTail && null != (node = LL.RemoveTail())) || (!bIsTail && null != (node = LL.RemoveHead())))
                {
                    Assert.AreNotEqual(null, node.VALUE);
                    Trace.WriteLine(string.Format("Consumer {0} - {1}", consumerId, node.VALUE));
                    consumed++;
                    await Task.Delay(rnd.Next(0, MaxConsumersRandomDelay));
                }

                Trace.WriteLine(string.Format("Consumer {0} is {1} -- Exited", consumerId, bIsTail ? "Tail" : "Head"));
                return(consumed);
            };


            // give a head start for consumers.
            for (int p = 1; p <= TailProducers + HeadProducers; p++)
            {
                //avoid hoisted variables.
                var isTail       = (TailProducers > 0 && p <= TailProducers);
                var producerName = string.Concat("P", p);
                producerTasks.Add(Task.Run(
                                      async() => await producer(isTail, producerName))
                                  );
            }

            for (int c = 1; c <= TailConsumers + HeadConsumers; c++)
            {
                var isTail       = (TailConsumers > 0 && c <= TailConsumers);
                var consumerName = string.Concat("C", c);
                consumerTasks.Add(Task.Run(
                                      async() => await consumer(isTail, consumerName))
                                  );
            }


            Task.WhenAll(producerTasks).Wait();
            Task.WhenAll(consumerTasks).Wait();



            // if after all said and done we still have items consume them.
            if (LL.Count > 0)
            {
                Trace.WriteLine("Consumers exited before producers completed work, creating a CX", "warnings");
                totalConsumed += Task <int> .Run(async() => await consumer(true, "CX")).Result;
            }

            // calculate all produced and consumed

            foreach (var p in producerTasks)
            {
                totalProduced += p.Result;
            }

            foreach (var c in consumerTasks)
            {
                totalConsumed += c.Result;
            }

            // are we clean?
            Trace.WriteLine(string.Format("completed produced:{0} consumed:{1}", totalProduced, totalConsumed), "info");
            Assert.AreEqual(totalProduced, totalConsumed);
            return(LL);
        }