简体   繁体   English

单例类触发事件仅一次

[英]Singleton class firing event only once

I am new writing singleton classes but I am running into a weird behavior.我是新编写单例类,但我遇到了一种奇怪的行为。 On my singleton class I have an event that is only firing once.在我的单身课程中,我有一个只触发一次的事件。 This event is the ReceiveCompleted of the System.Messaging.MessageQueue class.此事件是 System.Messaging.MessageQueue 类的 ReceiveCompleted。 My singleton class has a method GetCartAsync that requests information from another application via MSMQ to the "FleetClientQueue" queue which is the queue that the ReceiveCompleted is subscribed to.我的单例类有一个 GetCartAsync 方法,它通过 MSMQ 从另一个应用程序请求信息到“FleetClientQueue”队列,该队列是 ReceiveCompleted 订阅的队列。 Here is the singleton 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;
       
    }
}

Here is the code of how I am calling the method on the singleton class from a viewmodel class:这是我如何从视图模型类调用单例类上的方法的代码:

Cart = await CartRepository.Instance.GetCartAsync();

The weird part is that the first time GetCartAsync method is called the ReceiveCompleted event fires just fine.奇怪的是,第一次调用 GetCartAsync 方法时,ReceiveCompleted 事件触发得很好。 After that for some reason when I called the GetCartAsync from another view models in my application the ReceiveCompleted event is not fired.之后,出于某种原因,当我从应用程序中的另一个视图模型调用 GetCartAsync 时,不会触发 ReceiveCompleted 事件。 I can see the messages coming in into that queue on computer management and they just keep accumulating on the queue since it looks like they are not being processed by the singleton subscribed event.我可以在计算机管理上看到进入该队列的消息,并且它们只是在队列中不断累积,因为看起来它们没有被单例订阅事件处理。

Please if I can get some ideas of what is going on please.请如果我能得到一些关于正在发生的事情的想法。

The reason that you only get this callback once is that you only call BeginReceive once.你只得到一次这个回调的原因是你只调用BeginReceive一次BeginReceive It only consumes one item from the queue.它只消耗队列中的一项。

To continue consuming call BeginReceive again in the callback:要继续在回调中再次使用调用BeginReceive

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

This is the approach listed in the documentation:这是文档中列出的方法:

After debugging for some time your source code I observed that in the first line of the constructor of the CartRepository you have forgotten to delete a semicolon (;) at the end of the line.在调试了您的源代码一段时间后,我发现在CartRepository构造函数的第一行中,您忘记删除行尾的分号 (;)。 As such, your MessageQueue.Create tries to run every time even if the queue exists on the system creating an exception.因此,即使系统上存在队列创建异常,您的MessageQueue.Create也会尝试每次运行。

It is recommended that you try to catch all the exceptions and try to handle them accordingly.建议您尝试捕获所有异常并尝试相应地处理它们。 Also, you don't have an else statement after the creation and as such the following command re-initializes the queue without reason:此外,您在创建后没有else语句,因此以下命令无故重新初始化队列:

fleetClientQueue = new MessageQueue(".\\Private$\\FleetClientQueue");

What I would do is to rewrite the constructor to something like the following:我要做的是将构造函数重写为如下所示:

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

Be careful of the fact that I have created a constant string MessageQueueName and I use that string in my calls.请注意我创建了一个常量字符串MessageQueueName并在我的调用中使用该字符串这一事实。 Your GetCartAsync() method is using a different queue name and it is likely to be wrong (".\\Private$\\FleetClientServiceQueue").您的GetCartAsync()方法使用了不同的队列名称,它很可能是错误的(“.\\Private$\\FleetClientServiceQueue”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM