我在其他帖子上看到了此错误,但并非针对这种确切情况。

我有两个使用MessageQueue执行相同操作的类。因此,我将队列的创建和处理抽象为一个助手类。我收到此错误,并且我看不到如何可以多次处理队列。

对象'messageQueue'可以在方法'MsmqHelper.DisposeQueue(MessageQueue)'中多次处置。

在其中一个类中,这是使用队列的方式:

private MessageQueue _messageQueue;

然后,在该类的构造函数中:
this._messageQueue = MsmqHelper.InitializeQueue();

并不是真的很重要,但是为了完整起见,这是使用队列的地方:
this._messageQueue.Send(workflowCreated);

这是Dispose方法:
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
    if (disposing == false) { return; }

    MsmqHelper.DisposeQueue(this._messageQueue);
}

这是帮助程序类中实际上调用Dispose()的代码:
public static void DisposeQueue(MessageQueue messageQueue)
{
    if (messageQueue != null)
    {
        messageQueue.Close();
        messageQueue.Dispose();
        messageQueue = null;
    }
}

在这种情况下,队列在哪里可能被多次处置?

** 编辑 **

我认为在下面的对话中添加我的评论会很好。这是一个很好的总结,以及可接受的答案:

我想我现在明白了。 messageQueue方法参数与对该对象的原始(this._messageQueue)引用无关。因此,检查messageQueue是否为null,并将其设置为null并没有好处。即使在处置之后,调用方仍可以传递其变量(this._messageQueue)。因此,能够被处置一次以上。

顺便说一句,即使在调用方法中将调用者的变量(this._messageQueue)设置为null也无济于事。该问题仅存在于MsmqHelper.DisposeQueue()中。因此,答案是通过ref传递,或者根本不调用DisposeQueue()并在调用方法中完成所有操作。

**编辑2 **

尝试这个之后,我得到了同样的错误。我根本不明白。
public static void DisposeQueue(ref MessageQueue messageQueue)
{
    if (messageQueue == null) { return; }

    messageQueue.Close();
    messageQueue.Dispose();
    messageQueue = null;
}

**编辑3-错误? **

我开始认为这可能是一个错误。如果我评论messageQueue.Dispose(),该错误就会消失。但是,我可以在调用方法中一起调用messageQueue.Close()和messageQueue.Dispose()。去搞清楚。我想我将从调用方法中进行这些相同的调用,或者仅调用Close()或Dispose()而不是两者。

最佳答案

关闭将释放MessageQueue对象的所有资源。参见documentation here。该错误最有可能在CA中生成,因为它看到Close的执行路径也调用了Dispose。

从文档中:

    public  void ReceiveMessage()
    {
        // Connect to the a on the local computer.
        MessageQueue myQueue = new MessageQueue(".\\myQueue");

        // Set the formatter to indicate body contains an Order.
        myQueue.Formatter = new XmlMessageFormatter(new Type[]
            {typeof(String)});

        try
        {
            // Receive and format the message.
            Message myMessage1 = myQueue.Receive();
            Message myMessage2 = myQueue.Receive();
        }

        catch (MessageQueueException)
        {
            // Handle sources of any MessageQueueException.
        }

        // Catch other exceptions as necessary.

        finally
        {
            // Free resources.
            myQueue.Close();
        }

        return;
    }

关闭显然可以释放资源,但是如果尚未收集资源,则允许组件重新获取它们。最好先打开MessageQueue对象,然后使用它,然后在同一调用中将其关闭,而不要打开它一段时间然后再关闭,因为连接缓存消除了在重复调用中打开MessageQueue的开销。

* 更新*
看来,CA对于成员字段对待CA2202的方式与将一次性对象传递给方法的方式不同,即使该方法是该类专用的。无论如何,根据文档,您只需要调用Close()或Dispose()即可,而不必两者都调用。但是,我建议您更改设计,以便在消息操作范围内全部创建,使用然后关闭MessageQueue对象,如上述文档示例中的示例所示。

关于c# - MessageQueue处理一次以上,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9795008/

10-10 02:40