我正在设置一个标准的独立线程,用于在 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 问题中没有发现任何用处:
- How to stop consuming message from selective queue - RabbitMQ
- How to pause and resume consumption gracefully in rabbitmq, pika python
- What is the best way to safely end a java application with running RabbitMQ consumers
这里的问题是 consumer.Queue.Dequeue()
是一个阻塞调用。我尝试了这些选项:
调用
channel.BasicCancel(string tag)
。这会在阻塞调用中导致System.IO.EndOfStreamException
。出于显而易见的原因,我不想将此异常用作控制流的一部分。调用
consumer.Queue.Dequeue(int millisecondsTimeout, out T result)
并在循环迭代之间检查标志。这可以工作,但看起来很老套。
我想让线程正常退出并清理我可能拥有的任何非托管资源,这样就不会出现线程中止等情况。
感谢任何帮助。谢谢
最佳答案
带有超时和标志的 DeQueue 是实现它的方法。这是一种非常常见的模式,这就是为什么许多阻塞调用都带有启用超时的版本。
或者,抛出一个(已知的)异常对控制流来说不一定是坏事。优雅地关闭可能意味着实际捕获异常,评论“这是在请求 channel 关闭时抛出的”,然后干净地返回。这就是 TPL 的一部分如何与 CancellationToken 一起工作。
关于c# - 在 RabbitMQ 的 C# 客户端中优雅地停止消息消费的优雅方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26105228/