Skip to main content

DispatchConsumersAsync | Connection Factory | RabbitMQ | CSharp

  • DispatchConsumersAsync | Connection Factory | RabbitMQ | CSharp

info

Essa propriedade é das versões antigas do pacote do Rabbit para o C#. Para analisar melhor a forma nova, consulte a documentação clicando aqui.

O que é DispatchConsumersAsync

factory.DispatchConsumersAsync = true;

Essa configuração diz ao RabbitMQ.Client:

“Vou usar consumidores assíncronos (async/await), então despache as mensagens de forma compatível com Task.”

Ela muda a forma como o RabbitMQ chama o seu consumer internamente.


O que acontece sem isso (problema)

Por padrão (DispatchConsumersAsync = false):

  • O RabbitMQ chama o consumer de forma sincrona
  • Mesmo que você use async/await, o código roda bloqueando thread
  • O async vira praticamente um Task.Run().Wait()

Exemplo problemático ❌

var consumer = new AsyncEventingBasicConsumer(channel);

consumer.Received += async (sender, ea) =>
{
await ProcessarMensagemAsync(ea);
};

🔴 Se DispatchConsumersAsync = false:

  • Pode causar deadlock
  • Pode travar o consumer
  • Pode atrasar ACKs
  • Pode causar consumo lento e imprevisível

E o pior: não gera erro explícito.


O que muda quando é true

factory.DispatchConsumersAsync = true;

Agora:

  • O RabbitMQ executa o consumer em um contexto assíncrono real
  • O await não bloqueia a thread
  • O ACK acontece corretamente após o await
  • Melhor uso de threads
  • Mais estabilidade sob carga

Quando você DEVE usar

Você DEVE habilitar se:

  • Usa AsyncEventingBasicConsumer

  • Usa async/await no Received

  • Faz:

    • I/O (HTTP, DB, cache)
    • Delay
    • Processamento assíncrono

📌 Hoje, quase todos os consumers modernos precisam disso.


Quando NÃO precisa

Você NÃO precisa se:

  • Usa EventingBasicConsumer
  • Seu código é 100% síncrono
  • Não usa async/await

Exemplo síncrono:

var consumer = new EventingBasicConsumer(channel);

consumer.Received += (sender, ea) =>
{
ProcessarMensagem(ea);
};

Nesse caso:

DispatchConsumersAsync = false; // default

Diferença resumida (tabela)

SituaçãoDispatchConsumersAsync
Consumer síncrono❌ Não precisa
Consumer async/await✅ Obrigatório
AsyncEventingBasicConsumer✅ Obrigatório
HTTP / DB async✅ Obrigatório
Alta concorrência✅ Recomendado

Erro clássico em produção 🚨

“Meu consumer funciona em dev, mas trava em produção”

💥 Causa comum:

  • AsyncEventingBasicConsumer
  • DispatchConsumersAsync não habilitado

Exemplo correto completo ✅

var factory = new ConnectionFactory
{
HostName = "localhost",
DispatchConsumersAsync = true
};

var connection = factory.CreateConnection();
var channel = connection.CreateModel();

var consumer = new AsyncEventingBasicConsumer(channel);

consumer.Received += async (sender, ea) =>
{
await ProcessarMensagemAsync(ea);
channel.BasicAck(ea.DeliveryTag, false);
};

channel.BasicConsume(
queue: "fila.exemplo",
autoAck: false,
consumer: consumer
);

Regra de ouro 🧠

Se existe um await no consumer → DispatchConsumersAsync = true