/// <summary>Restart the consumer.</summary>
        /// <param name="consumer">The consumer.</param>
        internal void Restart(BlockingQueueConsumer consumer)
        {
            lock (this.consumersMonitor)
            {
                if (this.consumers != null)
                {
                    try
                    {
                        // Need to recycle the channel in this consumer
                        consumer.Stop();

                        // Ensure consumer counts are correct (another is not going
                        // to start because of the exception, but
                        // we haven't counted down yet)
                        this.cancellationLock.Release(consumer);
                        this.consumers.Remove(consumer);
                        consumer = this.CreateBlockingQueueConsumer();
                        this.consumers.Add(consumer);
                    }
                    catch (Exception e)
                    {
                        Logger.Warn(m => m("Consumer failed irretrievably on restart. {0}: {1}", e.Source, e.Message));

                        // Re-throw and have it logged properly by the caller.
                        throw;
                    }

                    var processor    = new AsyncMessageProcessingConsumer(consumer, this);
                    var taskExecutor = new Task(processor.Run);
                    taskExecutor.Start();
                }
            }
        }
        /// <summary>
        /// Perform start actions.
        /// </summary>
        protected override void DoStart()
        {
            base.DoStart();
            lock (this.consumersMonitor)
            {
                var newConsumers = this.InitializeConsumers();

                if (this.consumers == null)
                {
                    Logger.Info(m => m("Consumers were initialized and then cleared (presumably the container was stopped concurrently)"));
                    return;
                }

                if (newConsumers <= 0)
                {
                    Logger.Info(m => m("Consumers are already running"));
                    return;
                }

                var processors = new HashSet <AsyncMessageProcessingConsumer>();

                foreach (var consumer in this.consumers)
                {
                    var processor = new AsyncMessageProcessingConsumer(consumer, this);
                    processors.Add(processor);
                    var taskExecutor = new Task(processor.Run);
                    taskExecutor.Start();
                }

                foreach (var processor in processors)
                {
                    var startupException = processor.GetStartupException();
                    if (startupException != null)
                    {
                        throw new AmqpIllegalStateException("Fatal exception on listener startup", startupException);
                    }
                }
            }
        }
        /// <summary>
        /// Perform start actions.
        /// </summary>
        /// <exception cref="AmqpException">
        /// </exception>
        protected override void DoStart()
        {
            base.DoStart();
            lock (this.consumersMonitor)
            {
                this.InitializeConsumers();

                if (this.consumers == null)
                {
                    this.logger.Info("Consumers were initialized and then cleared (presumably the container was stopped concurrently)");
                    return;
                }

                var processors = new HashSet<AsyncMessageProcessingConsumer>();

                foreach (var consumer in this.consumers)
                {
                    var processor = new AsyncMessageProcessingConsumer(consumer, this);
                    processors.Add(processor);
                    this.taskExecutor.Execute(processor);
                }

                foreach (var processor in processors)
                {
                    var startupException = processor.GetStartupException();
                    if (startupException != null)
                    {
                        throw new AmqpException("Fatal exception on listener startup", startupException);
                    }
                }
            }
        }
        /// <summary>Restart the consumer.</summary>
        /// <param name="consumer">The consumer.</param>
        internal void Restart(BlockingQueueConsumer consumer)
        {
            lock (this.consumersMonitor)
            {
                if (this.consumers != null)
                {
                    try
                    {
                        // Need to recycle the channel in this consumer
                        consumer.Stop();

                        // Ensure consumer counts are correct (another is not going
                        // to start because of the exception, but
                        // we haven't counted down yet)
                        this.cancellationLock.Release(consumer);
                        this.consumers.Remove(consumer);
                        consumer = this.CreateBlockingQueueConsumer();
                        this.consumers.Add(consumer);
                    }
                    catch (Exception e)
                    {
                        Logger.Warn(m => m("Consumer failed irretrievably on restart. {0}: {1}", e.Source, e.Message));

                        // Re-throw and have it logged properly by the caller.
                        throw;
                    }

                    var processor = new AsyncMessageProcessingConsumer(consumer, this);
                    var taskExecutor = new Task(processor.Run);
                    taskExecutor.Start();
                }
            }
        }