【问题标题】:Rabbitmq Channel.Dispose vs channel = nullRabbitmq Channel.Dispose vs channel = null
【发布时间】:2021-07-22 06:27:22
【问题描述】:

我有这种类型的代码(伪):

IModel channel;
try
{
    channel = connection.CreateModel();
}
catch
{
    channel.dispose();
}

有时,由于连接不良,我从channel.Dispose 收到超时异常。如果我只做channel = null; 会发生什么?有这么错吗?它会在没有办法到达的情况下留在兔子身上吗?

【问题讨论】:

  • 如果他们回答了您的问题,请考虑接受其中一个答案,这样问题就不会保持开放。

标签: c# rabbitmq


【解决方案1】:

您对问题的描述是正确的。

如果channel 是非托管资源(而且很可能是,因为它有一个dispose 方法),那么通过将变量channel 设置为null,您将丢弃对它的引用。所以换句话说,你只是切断了在内存中与这个资源进行通信的唯一方法,但无论如何它仍然会驻留在内存中并占用一些空间(即使通过将引用设置为 null 而忘记了它在内存中的地址)。这正是所谓的内存泄漏

如果你的对象不是经常创建并且相对较小,这不会有什么坏处(当然这是一个糟糕的设计),但是一旦你的程序增长并产生许多内存泄漏,你就会陷入糟糕的境地并且你的内存将开始耗尽。

Dispose 中捕获异常也不好,如果你不注意的话,因为它也可能导致泄漏,但调试难度更大。

如果您确定通过重试处置将在稍后的某个时间起作用,则在Dispose 实现中的catch 块中重试再次调用Dispose。同样,您必须在这里小心,以免导致调试困难(比原始问题更糟)的泄漏。

实际上Dispose 中抛出异常是非常糟糕的,但是,有时您无法控制 3rd 方代码,您必须在 Dispose 中仔细处理该异常。

仅供参考,更好的处置实现是使用this dispose pattern

最后一句话,我猜你知道。如果这个资源是非托管的,那么你需要在 catch 中而不是在 finally 中调用这个 dispose,而不提到用 using 关键字包装资源的可能性。

【讨论】:

    【解决方案2】:

    根据经验,如果一个对象实现了IDisposable,并且您是该对象的所有者,那么您应该始终处置该对象。其他答案中已经给出了详细解释。

    通常,您会使用 using 块来执行此操作:

    using (var channel = connection.CreateModel())
    {
      ...
    }
    

    理想情况下,Dispose 不应引发异常。但如果是这样,你不应该忽略它们。问问自己:是什么导致了异常?如何解决实际问题?

    如果这是您认为可以安全忽略的特定情况,请确保仅专门捕获该异常,以确保您处理将来可能发生的任何其他错误。

    在通道的情况下,它只是在 Dispose 中调用Abort() 以优雅地发送再见,如果连接断开,它将失败。所以我认为在这种情况下,捕获并忽略该特定异常是安全的。

    有关如何处理 Dispose 中的异常的进一步讨论,另请参阅this SO 帖子。

    【讨论】:

      猜你喜欢
      • 2021-03-27
      • 2015-07-13
      • 1970-01-01
      • 2013-08-27
      • 1970-01-01
      • 2019-10-09
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      相关资源
      最近更新 更多