0

I am learning RabbitMq with .NET. According to the tutorial, simplest implementation of consumer looks like :

public class Receive
{
    public static void Main()
    {
    var factory = new ConnectionFactory() { HostName = "localhost" };
    using(var connection = factory.CreateConnection())
    using(var channel = connection.CreateModel())
    {
        channel.QueueDeclare(queue: "hello",
                             durable: false,
                             exclusive: false,
                             autoDelete: false,
                             arguments: null);

        var consumer = new EventingBasicConsumer(channel);
        consumer.Received += (model, ea) =>
        {
            var body = ea.Body;
            var message = Encoding.UTF8.GetString(body);
            Console.WriteLine(" [x] Received {0}", message);
        };
        channel.BasicConsume(queue: "hello",
                             noAck: true,
                             consumer: consumer);

        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }
  }
}

And it works correctly. However, I wanted to refactor it: let define functionality of receiver in separate method. It looks like :

public class Recieve
{
    private ConnectionFactory factory;
    public void ConsumeSimpleMessage(string queueName = "default")
    {
        using(var connection = factory.CreateConnection())
        {
            using(var channel = connection.CreateModel())
            {
                channel.QueueDeclare(queue: queueName, durable: false,
                    exclusive: false, autoDelete: false, arguments: null);
                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(message);
                };

                channel.BasicConsume(queue: queueName,
                             noAck: true,
                             consumer: consumer);
            }
        }


    }
    public Recieve(string hostName = "localhost")
    {
        factory = new ConnectionFactory() { HostName = hostName };
    }
}

And when I try to call this method in Main():

class Program
{
    static void Main(string[] args)
    {
        Recieve reciever = new Recieve();

        reciever.ConsumeSimpleMessage();

        Console.ReadLine();
    }
}

here it doesn't work. It show nothing. However, messages will be deleted, meaning that they were recieved. Why does it happen? Is there anything I didn't know about Event Handing?

Iskander Raimbaev
  • 1,322
  • 2
  • 17
  • 35

1 Answers1

2

Try to see if it works without doing using, Or if you want to use the using statement keep the Console.Read() inside the using statement and see if that works. You can keep the connection and channel open and don't have to close it manually.

If you really want to debug then you can put the breakpoint on the consumer.Receive and see if you can see the message staying unacked. That way you know when the message will be deleted.

Also I usually recommend using tracer for rabbitmq as it logs all the messages coming in the server which makes it easy to trace.

Mitra Ghorpade
  • 717
  • 4
  • 8
  • it works exactly after placing Console.Read() inside the using statements. I found some brief explanation about why it works here http://stackoverflow.com/questions/37192346/rabbitmq-basicconsume-and-event-driven-issues-relating-to-console-readline, but is there any deep\complete explanation, why should I call Console.Read() or Console.ReadLine() in order it to works? – Iskander Raimbaev Oct 21 '16 at 02:12
  • I think when you are using statements the objects are getting disposed, you can try not using the "using" statement for creating connection and channels. That might help. And as you are having a small application the connection and channel if kept open wont create lot of traffic. – Mitra Ghorpade Oct 21 '16 at 16:29