我想要一个有许多消费者收听新消息并处理它们的场景。当消息不为空时,消费者应该始终监听和处理消息。这是我写的代码:
string msg = null;
try
{
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
queueMessage = queue.getQueue("myQueue");
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
consumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: "myQueue", noAck: false, consumer: consumer);
while (true)
{
consumer.Received += (model, ea) =>
{
var body = ea.Body;
msg = Encoding.UTF8.GetString(body);
if (msg != null)
{
executeTask(msg);
}
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
};
channel.Dispose();
connection.Dispose();
consumer.Model.Dispose();
}//while(true)
}
}
catch (Exception e)
{
e.printStackTrace();
}
一段时间后,抛出OutOfMemoryException,很可能是因为没有“flush”机制且Received属性变满。一个粗略的解决方案可能是在while(true)中实例化连接,通道和消费者:
while (true)
{
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
queueMessage = queue.getQueue("myQueue");
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
consumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: "myQueue", noAck: false, consumer: consumer);
consumer.Received += (model, ea) =>
{
...
我完全不相信这是一个很好的解决方案,因为多个线程不断打开和关闭。可能是处理这种行为的另一类,还是我错过了什么?
答案 0 :(得分:0)
首先,应在一个对象中创建整个工厂连接和客户端,在您的服务/程序的生命周期继续进行时,您将始终对其进行引用,以使它们不会被GC。尤其不要将它们放在using([])中。想要多个客户? ->单独的线程和实例 其次,您不需要使用``while''和频道重新创建功能,因为一旦您向使用者注册了一些工作即可。接收并随后初始化频道.BasicConsume,工作调用将保存在内存中并在每个入站调用给消费者的信息