示例#1
0
 public void InitializationTest()
 {
     using (var q = new ConcurrentDispatcher <string>())
     {
         Assert.IsTrue(q.IsEmpty);
     }
 }
示例#2
0
        public void OrderedSequentialTest()
        {
            const int    N      = 1_000_000;
            const string FORMAT = "0000000000";
            const string INIT   = "init";

            var newItemCounter = 0;
            var emptyCounter   = 0;
            var q = new ConcurrentDispatcher <string>();

            q.NewItem += (sender, e) => Interlocked.Increment(ref newItemCounter);
            q.Empty   += (sender, e) => Interlocked.Increment(ref emptyCounter);

            // enqueue N items
            for (int i = 0; i < N; i++)
            {
                q.Enqueue(i.ToString(FORMAT));
            }

            Assert.IsFalse(q.IsEmpty);

            // dequeue N items
            for (int i = 0; i < N; i++)
            {
                var s         = INIT;
                var returnVal = q.TryDequeue(ref s);
                Assert.IsTrue(returnVal);
                Assert.AreNotEqual(INIT, s);
                Assert.IsNotNull(s);
                Assert.AreEqual(i.ToString(FORMAT), s);
            }

            Assert.IsTrue(q.IsEmpty);

            Assert.AreEqual(N, newItemCounter);
            Assert.AreEqual(1, emptyCounter);

            // try dequeue empty queue

            var s2         = INIT;
            var returnVal2 = q.TryDequeue(ref s2);

            Assert.IsFalse(returnVal2);
            Assert.AreEqual(INIT, s2);

            // dispose dispatcher
            Assert.IsFalse(q.IsDisposed);
            q.Dispose();
            Assert.IsTrue(q.IsDisposed);

            string s3 = null;

            // try non-blocking dequeue
            Assert.IsFalse(q.TryDequeue(ref s3));
            // try blocking dequeue
            Assert.IsFalse(q.Dequeue(ref s3));
        }
示例#3
0
        public void ConcurrentTest()
        {
            const int    N         = 1_000_000;
            const int    PRODUCERS = 3;
            const int    CONSUMERS = 3;
            const string FORMAT    = "0000000000";
            var          rand      = new Random();

            var q = new ConcurrentDispatcher <string>();

            // prepare producer bags
            var producerItems = new List <string> [PRODUCERS];

            for (int i = 0; i < producerItems.Length; i++)
            {
                producerItems[i] = new List <string>();
            }

            // fill producer bags randomly
            for (int i = 0; i < N; i++)
            {
                producerItems[rand.Next(producerItems.Length)].Add(i.ToString(FORMAT));
            }

            // prepare event check
            var productionCount = 0;
            var emptyCount      = 0;

            q.NewItem += (sender, e) => Interlocked.Increment(ref productionCount);
            q.Empty   += (sender, e) => Interlocked.Increment(ref emptyCount);

            // prepare consumer bags
            var consumerItems = new List <string> [CONSUMERS];

            for (int i = 0; i < consumerItems.Length; i++)
            {
                consumerItems[i] = new List <string>();
            }

            // create producer threads
            var producers = new Thread[PRODUCERS];

            for (int i = 0; i < producers.Length; i++)
            {
                var threadIndex = i;
                producers[threadIndex] = new Thread(() =>
                {
                    foreach (var item in producerItems[threadIndex])
                    {
                        q.Enqueue(item);
                    }
                });
            }

            // create comsumer threads
            var consumers = new Thread[CONSUMERS];

            for (int t = 0; t < consumers.Length; t++)
            {
                var threadIndex = t;
                consumers[threadIndex] = new Thread(() =>
                {
                    string s = null;
                    while (q.Dequeue(ref s))
                    {
                        consumerItems[threadIndex].Add(s);
                    }
                });
            }

            // start threads
            for (int i = 0; i < consumers.Length; i++)
            {
                consumers[i].Start();
            }
            for (int i = 0; i < producers.Length; i++)
            {
                producers[i].Start();
            }

            // wait for producer threads to end
            for (int i = 0; i < producers.Length; i++)
            {
                producers[i].Join();
            }

            // check for production count
            Assert.AreEqual(N, productionCount, "The NewItem event was not fired the right number of times.");

            // wait for consumer threads to block
            for (int i = 0; i < consumers.Length; i++)
            {
                var thread = consumers[i];
                while (thread.ThreadState != ThreadState.WaitSleepJoin)
                {
                    Thread.Sleep(1);
                }
            }

            // check for empty signal
            Assert.IsFalse(emptyCount == 0, $"The Empty event was not fired once.");

            // dispose the dispatcher
            q.Dispose();

            // wait for consumer threads to end
            for (int i = 0; i < consumers.Length; i++)
            {
                consumers[i].Join();
            }

            // check completeness in consumer items
            var consumptionIndex = new int[N];

            for (int i = 0; i < consumerItems.Length; i++)
            {
                Assert.IsTrue(consumerItems[i].Count > 0, "At least one consumer did nothing.");

                var last = string.Empty;
                foreach (var item in consumerItems[i])
                {
                    // count occurance
                    var itemNo = int.Parse(item);
                    consumptionIndex[itemNo]++;
                }
            }
            var unconsumedCount       = 0;
            var multiConsumptionCount = 0;

            for (int i = 0; i < N; i++)
            {
                if (consumptionIndex[i] == 0)
                {
                    unconsumedCount++;
                }
                if (consumptionIndex[i] > 1)
                {
                    multiConsumptionCount++;
                }
            }
            Assert.AreEqual(0, unconsumedCount, $"{unconsumedCount} items were not consumed");
            Assert.AreEqual(0, multiConsumptionCount, $"{multiConsumptionCount} items were consumed more than once.");
        }