我正在设置一个标准的独立线程,在C#中监听RabbitMQ。假设在线程中侦听的方法如下所示:
public void Listen()
{
using (var channel = connection.CreateModel())
{
var consumer = SetupQueues(channel);
while (true)
{
var ea = consumer.Queue.Dequeue(); // blocking call
handler.HandleMessage(channel, ea);
}
}
}
在RabbitMQ的C#客户端中优雅地停止消息消息的优雅方法是什么?请记住,我在RabbitMQ示例/文档或这些SO问题中没有发现任何用处:
此处的问题是consumer.Queue.Dequeue()
是阻止来电。我尝试过这些选项:
致电channel.BasicCancel(string tag)
。这会在阻止调用中导致System.IO.EndOfStreamException
。出于显而易见的原因,我不想将此异常用作控制流程的一部分。
调用consumer.Queue.Dequeue(int millisecondsTimeout, out T result)
并在循环迭代之间检查标志。这可以起作用,但看起来很糟糕。
我想让线程优雅地退出并清理我可能拥有的任何非托管资源,因此没有线程中止等等。
感谢任何帮助。感谢
答案 0 :(得分:1)
DeQueue的超时&国旗是这样做的方式。它是一种非常常见的模式,也就是为什么许多阻塞调用都提供了启用超时的版本。
或者,抛出(已知的)异常并不一定是控制流的坏事。优雅地关闭可能意味着实际捕获异常,评论"当请求通道关闭"然后干净地返回时抛出此异常。这就是TPL的一部分如何与CancellationToken一起使用。
答案 1 :(得分:1)
阻止方法不是属性事件驱动的。
我不建议他们使用consumer.Queue.Dequeue();
无论如何,我通常不使用consumer.Queue.Dequeue();
我以这种方式扩展默认消费者:
class MyConsumer : DefaultBasicConsumer {
public MyConsumer(IModel model):base(model)
{
}
public override void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, byte[] body) {
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
}
}
class Program
{
static void Main(string[] args)
{
var factory = new ConnectionFactory() { Uri = "amqp://aa:bbb@lemur.cloudamqp.com/xxx" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare("hello", false, false, false, null);
var consumer = new MyConsumer(channel);
String tag = channel.BasicConsume("hello", true, consumer);
Console.WriteLine(" [*] Waiting for messages." +
" any key to exit");
Console.ReadLine();
channel.BasicCancel(tag);
/*while (true)
{
/////// DON'T USE THIS
var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
}*/
}
}
}
}
通过这种方式,您没有阻止方法,并且可以正确释放所有资源。
修改强>
我认为使用 ctrl + C 打破程序总是错误的。