Used for countdown events. When the count reaches zero, the event will be set.
Наследование: IDisposable
        public void Retry_Queue_Receives_Initial_Failures()
        {
            using (var serviceBusRuntime = Create.MsmqRuntime<IContract>())
            {
                ServiceBusTest tester = new ServiceBusTest(serviceBusRuntime);

                string message = "Publish this message";
                ContractImplementation ci = new ContractImplementation();
                ci.SetFailCount(1);

                tester.OnlyRetryOnce();
                tester.AddTestListener();

                tester.AddTestSubscription(ci, new PassThroughMessageFilter());

                bool failFirst = false;
                bool deliverSecond = false;

                tester.StartAndStop(() =>
                {
                    CountdownLatch latch = new CountdownLatch(2+1);

                    serviceBusRuntime.MessageDelivered += (o, mdea) =>
                    {
                        int tick; if ((tick = latch.Tick()) == 0) deliverSecond = true; Console.WriteLine("Tick deliver " + tick);
                    };
                    serviceBusRuntime.MessageDeliveryFailed += (o, mdfea) =>
                    {
                        int tick; if ((tick = latch.Tick()) == 1) failFirst = true; Console.WriteLine("Tick fail " + tick);
                    };

                    serviceBusRuntime.PublishOneWay(new PublishRequest(typeof(IContract), "PublishThis", message));

                    // Wait for delivery
                    latch.Handle.WaitOne(TimeSpan.FromMinutes(1), false); // give it a minute

                });

                Assert.AreEqual(true, failFirst);
                Assert.AreEqual(true, deliverSecond);

                Assert.AreEqual(1, ci.PublishedCount);
                Assert.AreEqual(message, ci.PublishedMessages[0]);

                tester.VerifyQueuesEmpty();
            }
        }
        void waitForDeliveries(int deliveryCount, int failureCount, bool includeFailures, TimeSpan timeout, Action inner)
        {
            using (CountdownLatch latch = new CountdownLatch(deliveryCount))
            {
                using (CountdownLatch failLatch = new CountdownLatch(failureCount))
                {

                    EventHandler<MessageDeliveryEventArgs> delivered = (o, mdea) => { Console.WriteLine("s");  latch.Tick(); };
                    EventHandler<MessageDeliveryFailedEventArgs> deliveryFailed = (o, mdfa) => { Console.WriteLine("f"); failLatch.Tick(); };

                    serviceBusRuntime.MessageDelivered += delivered;
                    if (includeFailures) serviceBusRuntime.MessageDeliveryFailed += deliveryFailed;

                    try
                    {
                        StartAndStop(() =>
                        {
                            inner();

                            if (!WaitHandle.WaitAll(new WaitHandle[] { latch.Handle, failLatch.Handle } , timeout))
                            {
                                throw new TimeoutException("timeout expired");
                            }
                        });
                    }
                    finally
                    {
                        serviceBusRuntime.MessageDelivered -= delivered;
                        if (includeFailures) serviceBusRuntime.MessageDeliveryFailed -= deliveryFailed;
                    }
                }

            }
        }