单例 class 仅触发一次事件

Singleton class firing event only once

我是新写单例 classes 但我 运行 有一种奇怪的行为。在我的单身人士 class 上,我有一个只触发一次的事件。此事件是 System.Messaging.MessageQueue class 的 ReceiveCompleted。我的单身人士 class 有一个方法 GetCartAsync,它通过 MSMQ 从另一个应用程序请求信息到“FleetClientQueue”队列,这是订阅 ReceiveCompleted 的队列。这是单例 class:

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;
       
    }
}

这是我如何从视图模型 class 调用单例 class 方法的代码:

Cart = await CartRepository.Instance.GetCartAsync();

奇怪的是,第一次调用 GetCartAsync 方法时,ReceiveCompleted 事件会正常触发。之后由于某种原因,当我从我的应用程序中的另一个视图模型调用 GetCartAsync 时,没有触发 ReceiveCompleted 事件。我可以在计算机管理上看到消息进入该队列,并且它们一直在队列中累积,因为看起来它们没有被单例订阅事件处理。

如果我能对正在发生的事情有一些想法,拜托了。

调试您的源代码一段时间后,我发现在 CartRepository 的构造函数的第一行中,您忘记删除行尾的分号 (;)。因此,您的 MessageQueue.Create 每次都会尝试 运行,即使队列存在于创建异常的系统上也是如此。

建议您尝试捕获所有异常并尝试相应地处理它们。此外,您在创建后没有 else 语句,因此以下命令 re-initializes the queue without reason:

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")。

你只得到一次这个回调的原因是你只调用了一次BeginReceive。 它只消耗队列中的一项。

要继续消费,请在回调中再次调用 BeginReceive

private void FleetClientQueue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
    _cart = (Cart)e.Message.Body;
    expectedEchoReceived.Set();
    // Restart the asynchronous receive operation.
    fleetClientQueue.BeginReceive();
}

这是文档中列出的方法: