我有一个用C#编写的RabbitMQ客户端程序。当应用程序在基于控制台的应用程序中工作时(由于Console.ReadLine阻止了执行),在基于Windows窗体的应用程序中不起作用。在Windows Form应用程序中,执行不会在Console.ReadLine上等待,并在完成时终止。我正在寻找一种解决方案,其中,我的侦听器会不断监视服务器中的新消息而不会被终止。 这是客户端代码:
try {
var factory = new ConnectionFactory() { HostName = "xxx" , UserName ="xxx", Password="xxx"};
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "call_notify", type: "fanout");
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName,
exchange: "call_notify",
routingKey: "");
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,
autoAck: true,
consumer: consumer);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine(); // Program does'nt wait here in windows form based application
}
}
答案 0 :(得分:2)
using
,因为那样会立即处理掉所有内容这样,它们将一直存在直到应用程序终止。
答案 1 :(得分:1)
如果您希望代码在两个平台上都可以工作,那么最好创建一个抽象层来公开消息并处理启动/停止逻辑。
public class RabbitMQManager : IDisposable
{
private bool _disposed = false;
private IModel _channel;
private IConnection _connection;
public event EventHandler<string> MessageReceived;
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_channel?.Dispose();
_connection?.Dispose();
}
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
}
public void Connect()
{
var factory = new ConnectionFactory { HostName = "xxx", UserName = "xxx", Password = "xxx" };
_connection = factory.CreateConnection();
_channel = _connection.CreateModel();
_channel.ExchangeDeclare(exchange: "call_notify", type: "fanout");
string queueName = _channel.QueueDeclare().QueueName;
_channel.QueueBind(queue: queueName,
exchange: "call_notify",
routingKey: "");
var consumer = new EventingBasicConsumer(_channel);
consumer.Received += (model, ea) =>
{
byte[] body = ea.Body;
string message = Encoding.UTF8.GetString(body);
MessageReceived?.Invoke(this, message);
};
_channel.BasicConsume(queue: queueName,
autoAck: true,
consumer: consumer);
}
}
然后,您可以通过创建类的实例并订阅MessageReceived
事件,在所需的任何项目类型中使用此方法。例如,WinForms实现就是:
public class MyForm : Form
{
private RabbitMQManager _rabbitMQManager;
public MyForm() { _rabbitMQManager = new RabbitMQManager(); }
// you can call this from constructor or some event
public void Connect()
{
_rabbitMQManager.MessageReceived = (sender, msg) => someLabel.Text = msg;
_rabbitMQManager.Connect();
}
}
请参阅以下问答,了解如何覆盖MyForm.Dispose
,以便正确处置资源:How do I extend a WinForm's Dispose method?
在控制台应用程序中,可能只是:
using (var manager = new RabbitMQManager())
{
manager.MessageReceived += (sender, msg) => Console.WriteLine(msg);
manager.Connect();
Console.Read();
}
答案 2 :(得分:-2)
谢谢大家!根据您的所有建议,我找到了多种方法来实现这一目标。
我实现此目的的方法是将Factory,Connection和Channel设置为类变量,并在MainForm构造函数中定义它们。这样,对象得以保留,程序继续监听传入的消息。