Search code examples
c#.netrabbitmqtopshelf

RabbitMQ EventBasicConsumer not working


BACKGROUND INFO

I have a queue (for emails) in RabbitMQ, and want to build a consumer for it. The queue is used by another .NET app for sending emails to customers. I wanted the emailing logic to sit outside of the .NET app, and also have the benefits of durability ...etc that RabbitMQ offers.

ISSUE

The .NET app is able to publish/push emails onto the queue, but I have difficulty building the consumer! Here's my code for the consumer:

// A console app that would be turned into a service via TopShelf
public void Start()
{
  using (_connection = _connectionFactory.CreateConnection())
  {
    using (var model = _connection.CreateModel())
    {
      model.QueueDeclare(_queueName, true, false, false, null);
      model.BasicQos(0, 1, false);

      var consumer = new EventingBasicConsumer(model);
      consumer.Received += (channelModel, ea) =>
      {
        var message = (Email) ea.Body.DeSerialize(typeof(Email));
        Console.WriteLine("----- Email Processed {0} : {1}", message.To, message.Subject);
        model.BasicAck(ea.DeliveryTag, false);
      };
      var consumerTag = model.BasicConsume(_queueName, false, consumer);
    }
  }
}

The code above should be able to grab messages off the queue and process them (according to this official guide), but this isn't happening.


Solution

  • The problem is premature connection disposal. People often think that BasicConsume is a blocking call, but it is not. It will return almost immediately, and the very next statement is disposing (closing) of channel and connection which of course will cancel your subscription. So to fix - store connection and model in private fields and dispose them only when you are done with queue consumption.