title: Clean up for queues and connections - console app hangs on exit
body: <p>Using RabbitMQ in a very simple console app I'm running into a problem where the console app isn't quiting at the end of execution and I <em>think</em> it might be because I'm hanging on to something in RabbitMQ. So what exactly do I need to dispose of? I have a class <code>Queue</code> class that looks something like this:</p>
  
  <pre><code>public class ManagementQueue : IDisposable
  {
      private IConnection connection;
      private IModel channel;
      private string privateQueueName;
      private EventingBasicConsumer consumer;
  
      public event EventHandler SomeEvents;     
  
      public ManagementQueue()
      {
          var factory = new ConnectionFactory() 
          { 
              HostName = Properties.Settings.Default.RabbitMQServer,
              UserName = Properties.Settings.Default.RabbitMQUser,
              Password = Properties.Settings.Default.RabbitMQPassword
          };
          connection = factory.CreateConnection();
          channel = connection.CreateModel();
  
          privateQueueName = channel.QueueDeclare().QueueName;        
  
          channel.QueueDeclare(queue: Properties.Settings.Default.ManagementQueueName,
              durable: true,
              exclusive: false,
              autoDelete: false,
              arguments: null);
  
        channel.ExchangeDeclare(Properties.Settings.Default.BroadcastExchange, "fanout");       
          channel.ExchangeDeclare(Properties.Settings.Default.DirectExchange, "direct");          
  
          channel.QueueBind(privateQueueName,
              Properties.Settings.Default.DirectExchange,
              privateQueueName);
  
          channel.QueueBind(Properties.Settings.Default.ManagementQueueName,
              Properties.Settings.Default.DirectExchange,
              "fromManager");
  
          channel.BasicQos(0, 1, false);
      }
  
      public void StartListening()
      {
          consumer = new EventingBasicConsumer(channel);
          consumer.Received += ReceivedHandler;
  
          channel.BasicConsume(queue: privateQueueName, 
              noAck: true, 
              consumer: consumer);
      }
  
      public void StopListening()
      {
          consumer.Received -= ReceivedHandler;
      }
  
      private void ReceivedHandler(object model, BasicDeliverEventArgs ea)
      {
          // Do some stuff...
      }
  
      public void SomeFunction()
      {
          // send out some message...
          var props = channel.CreateBasicProperties();
          props.ReplyTo = privateQueueName;
  
          channel.BasicPublish(exchange: Properties.Settings.Default.BroadcastExchange,
                   routingKey: "",
                   basicProperties: props,
                   body: null);
      }
  
      public void Dispose()
      {
          if (channel != null)
          {
              channel.Dispose();
              channel = null;
          }
          if (connection != null)
          {
              connection.Dispose();
              connection = null;
          }
      }
  }
  </code></pre>
  
  <p>And in the console I have something like:</p>
  
  <pre><code>static void Main(string[] args)
  {
     if (!args.Any())
     {
         // This works fine exiting here
         return;
     }
     var queue = new ManagementQueue();
     queue.SomeEvents += (o,e) =&gt; { // do something };
     queue.StartListening();
     queue.SomeFunction();
  
     while (!somecondition)
     {
         // do some other stuff
     }
     queue.StopListening();
     queue.Dispose();
     return;    // app should quit here, but doesn't???
  }
  </code></pre>
  
  <p>I'm suspicious that it might be something going on with the consumer, but there doesn't appear to be any methods to dispose, close or disconnect it. No where am I explicitly creating any new threads or any tight loops (other than the <code>while</code> loop, but that does exit when the condition evaluates to false).</p>