问题描述
我是写单例类的新手,但是我遇到了一种奇怪的行为。在我的单例课程中,我有一个仅触发一次的事件。此事件是System.Messaging.MessageQueue类的ReceiveCompleted。我的单例类具有方法GetCartAsync,该方法通过MSMQ从另一个应用程序向“ FleetClientQueue”队列请求信息,该队列是ReceiveCompleted所预订的队列。这是单例课程:
public sealed class CartRepository : ICartRepository
{
private CartRepository()
{
if (!MessageQueue.Exists(string.Format(".\\Private$\\FleetClientQueue"))) ;
{
fleetClientQueue = MessageQueue.Create(".\\Private$\\FleetClientQueue");
fleetClientQueue.SetPermissions("Everyone",MessageQueueAccessRights.FullControl,AccessControlEntryType.Allow);
}
fleetClientQueue = new MessageQueue(".\\Private$\\FleetClientQueue");
fleetClientQueue.Formatter = new Xmlmessageformatter(new[] { typeof(Cart) });
fleetClientQueue.ReceiveCompleted += FleetClientQueue_ReceiveCompleted;
fleetClientQueue.BeginReceive();
}
static ManualResetEvent expectedEchoReceived = new ManualResetEvent(false);
Cart _cart = new Cart();
static MessageQueue fleetClientQueue;
private static CartRepository instance = null;
public static CartRepository Instance
{
get
{
if (instance == null)
{
instance = new CartRepository();
}
return instance;
}
}
private void FleetClientQueue_ReceiveCompleted(object sender,ReceiveCompletedEventArgs e)
{
_cart = (Cart)e.Message.Body;
expectedEchoReceived.Set();
}
public async Task<Cart> GetCartAsync()
{
MessageQueue fleetClientServiceQueue;
fleetClientServiceQueue = new MessageQueue(".\\Private$\\FleetClientServiceQueue");
fleetClientServiceQueue.Formatter = new Binarymessageformatter();
fleetClientServiceQueue.Send("RequestCartinformation");
expectedEchoReceived.Reset();
expectedEchoReceived.WaitOne(5000);
return _cart;
}
}
Cart = await CartRepository.Instance.GetCartAsync();
奇怪的是,第一次调用GetCartAsync方法ReceiveCompleted事件就可以触发。之后,由于某种原因,当我从应用程序中的另一个视图模型调用GetCartAsync时,不会触发ReceiveCompleted事件。我可以在计算机管理中看到进入该队列的消息,并且它们只是在队列中不断累积,因为看起来好像单例订阅事件未对其进行处理。
请让我对发生的事情有所了解。
解决方法
仅获得一次回调的原因是您仅调用了BeginReceive
。
它只消耗队列中的一项。
要继续使用回叫,请再次使用BeginReceive
:
private void FleetClientQueue_ReceiveCompleted(object sender,ReceiveCompletedEventArgs e)
{
_cart = (Cart)e.Message.Body;
expectedEchoReceived.Set();
// Restart the asynchronous receive operation.
fleetClientQueue.BeginReceive();
}
这是文档中列出的方法:
,在调试您的源代码一段时间后,我发现在CartRepository
的构造函数的第一行中,您忘记删除行末的分号(;)。因此,即使队列上存在创建异常的系统,您的MessageQueue.Create
也会尝试每次运行。
建议您尝试捕获所有异常并尝试相应地处理它们。另外,创建后没有else
语句,因此以下命令无需任何理由即可重新初始化队列:
fleetClientQueue = new MessageQueue(".\\Private$\\FleetClientQueue");
我要做的是将构造函数重写为如下内容:
private const string MessageQueueName = ".\\Private$\\FleetClientQueue";
private CartRepository()
{
try
{
if (!MessageQueue.Exists(MessageQueueName))
{
fleetClientQueue = MessageQueue.Create(MessageQueueName);
fleetClientQueue.SetPermissions("Everyone",MessageQueueAccessRights.FullControl,AccessControlEntryType.Allow);
}
else
{
fleetClientQueue = new MessageQueue(MessageQueueName);
}
fleetClientQueue.Formatter = new XmlMessageFormatter(new[] { typeof(Cart) });
fleetClientQueue.ReceiveCompleted += FleetClientQueue_ReceiveCompleted;
fleetClientQueue.BeginReceive();
}
catch (Exception e)
{
// do something here. eg.
// log the error in a Log file,display message to the user or whatever...
}
}
请注意以下事实:我创建了一个常量字符串MessageQueueName
,并且在调用中使用了该字符串。您的GetCartAsync()
方法使用了不同的队列名称,这很可能是错误的(“。\ Private $ \ FleetClientServiceQueue”)。