title: How to correctly finish RabbitMq consumer and wait to RabbitMq consumer threads (library consumer callbacks) after close connection and model?
body: <p>I have RabbitMq consumer (<code>RabbitMQ.Client.Events.EventingBasicConsumer</code>) that process incoming messages.</p>
  <p>But I noticed that if close connection and model they does not wait to finish library processing threads. E.g.:</p>
  <ol>
  <li>If I will add thread sleep for several seconds to <code>EventingBasicConsumer::Received</code> callback then I noticed that <code>Close</code> functions (<code>Close()</code> of <code>IModel</code> and <code>IConnection</code>) finished before exit from this consumer callback</li>
  <li>After finish <code>Close</code> functions I continue to receive some messages to <code>EventingBasicConsumer::Received</code> callback.</li>
  </ol>
  <p>So how to correctly close consumer and wait to finish all processing's in consumer threads of library?
  I want to ensure that I will not receive any incoming messages from library for my consumer after close all connections/consumers.</p>
  <p><strong>Simplified code:</strong></p>
  <pre><code>RunTest()
  {
      MyConsumer consumer = new MyConsumer();
      consumer.Connect();
      
      // Wait before close for process some count of incoming messages
      Thread.Sleep(10 * 1000);
      
      consumer.Disconnect();
  }
  
  class MyConsumer
  {
      private RabbitMQ.Client.IConnection     m_Connection = null;
      private RabbitMQ.Client.IModel          m_Channel = null;
          
      public void Connect()
      {
          //
          // ...
          //
  
          m_Channel = m_Connection.CreateModel();
          m_Consumer = new RabbitMQ.Client.Events.EventingBasicConsumer(m_Channel);
          m_Consumer.Received += OnRequestReceived;
          m_ConsumerTag = m_Channel.BasicConsume(m_Config.RequestQueue, false, m_Consumer);
      }
          
      public void Disconnect()
      {
          Console.WriteLine(&quot;---&gt; IModel::Close()&quot;);
          m_Channel.Close();
          Console.WriteLine(&quot;&lt;--- IModel::Close()&quot;);
          
          Console.WriteLine(&quot;---&gt; RabbitMQ.Client.IConnection::Close()&quot;);
          m_Connection.Close();
          Console.WriteLine(&quot;&lt;--- RabbitMQ.Client.IConnection::Close()&quot;);
          
          //
          // Maybe there is need to do some RabbitMQ API call of channel/model
          // for wait to finish of all consumer callbacks?
          //
          
          m_Channel = null;
          m_Connection = null;
      }
  
      private void OnRequestReceived(object sender, RabbitMQ.Client.Events.BasicDeliverEventArgs mqMessage)
      {
          Console.WriteLine(&quot;---&gt; MyConsumer::OnReceived&quot;);
          
          Console.WriteLine(&quot;MyConsumer: ThreadSleep started&quot;);
          Thread.Sleep(10000);
          Console.WriteLine(&quot;MyConsumer: ThreadSleep finished&quot;);
          
          if (m_Channel != null)
          {
              m_Channel.BasicAck(mqMessage.DeliveryTag, false);
          }
          else
          {
              Console.WriteLine(&quot;MyConsumer: already closed&quot;);
          }
          
          Console.WriteLine(&quot;&lt;--- MyConsumer::OnReceived&quot;);
      }
  }
  </code></pre>
  <p><strong>Result:</strong></p>
  <pre><code>---&gt; MyConsumer::OnReceived
  MyConsumer: ThreadSleep started
  
  ---&gt; IModel::Close() 
  &lt;--- IModel::Close() 
  ---&gt; RabbitMQ.Client.IConnection::Close() 
  &lt;--- RabbitMQ.Client.IConnection::Close() 
  
  MyConsumer: ThreadSleep finished
  MyConsumer: already closed
  &lt;--- MyConsumer::OnReceived
  
  ---&gt; MyConsumer::OnReceived
  MyConsumer: ThreadSleep started
  MyConsumer: ThreadSleep finished
  MyConsumer: already closed
  &lt;--- MyConsumer::OnReceived
  </code></pre>
  <p>How we see <code>MyConsumer::OnReceived</code> was finished after exit from <code>Close()</code> functions of Consumer and Connection. Moreover how we see there is one more message which was income after finish of previous call of OnReceived and close connection (that means that RqbbitMq continues to process consumer messages until the internal library queues are empty ignoring the fact that consumer and connection are already closed).</p>