【问题标题】:Do I have to use a “using” statement in a short method?我必须在简短的方法中使用“使用”语句吗?
【发布时间】:2011-10-11 21:19:32
【问题描述】:

我是否必须使用using 语句才能立即处置,即使在方法中?或者该方法的结束会导致包括图形在内的所有局部变量的自动Dispose? (我问这个是因为我看到在方法末尾有 Dispose 调用的示例,并且想知道这是否真的有必要。)

谢谢。

【问题讨论】:

    标签: c# garbage-collection dispose using


    【解决方案1】:

    是的,你知道。超出范围不会做任何事情;它不调用Dispose(),不进行垃圾收集,也不调用终结器。

    如果类型是IDisposable,则。您的工作是自己整理(假设此时对象实际上已“完成”)。

    不这样做的可能副作用:

    • 文件保持打开状态并导致访问异常 (FileStream)
    • 连接保持打开状态并导致池饱和 (DbConnection)
    • 非托管句柄会饱和并导致资源不足(任何 winforms/etc)
    • 事务保持打开状态并导致阻塞 (TransactionScope / DbTransaction)

    基本上是坏事。

    此外,在大多数情况下,如果您在方法底部看到Dispose(),则最好使用using某些情况下这是不可能的(例如,对象上的字段),但重点仍然存在:听起来这些都是不好的例子。

    【讨论】:

    • 但它是通过 Go 还是收取 200 美元?
    • @Andrew 前提是您预先同意的遣散费是 200 美元,因为您因留下僵尸交易而导致广泛的网络中断;p
    • 所以(根据你的 cmets 的另一个答案)如果我打电话给 Dispose 以获得 Graphics - 内存不会立即被 GC,只有当 GC 进行循环时?
    • @ispiro 非常依赖于 which 内存;p 调用 dispose 将释放 windows-handle,并释放 unmanaged 内存;但是,不涉及GC托管内存收集
    【解决方案2】:

    你从来没有去处理一个对象。但是,如果您想更早地释放非托管资源,而不是在 GC 处理它时(即它处理 fReachable 队列时),那么 是的,您应该,因为方法的范围不能确定何时将调用一次性对象的 finalize。

    您可能想阅读 Jeffrey Richter 的 Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework 了解更多信息

    正如 delnan 指出的那样,如果您使用的资源存在硬性限制,那么如果您让 GC 回收而不是调用 Dispose,您更有可能受到影响。数据库连接是这种资源的一个很好的例子,当然也是创建NumberOfReclaimedConnections 性能计数器的原因。

    【讨论】:

    • .NET 垃圾收集器是否甚至会进入非托管空间并在那里清理资源?我的印象是它没有。
    • Dispose 方法可能会做更多垃圾收集器不会做的清理工作。它可以关闭文件,清理网络套接字,等等。如果某些东西被设计为处置,您应该在某个时候调用处置。
    • 您也不必使用换行符...实际上,与处理相比,这是可选的。如果终结器中没有 Dispose 调用,则您会泄漏。如果在此之后没有偶然调用终结器,则您会泄漏(可能很长时间)一段时间。如果一个人可以同时打开的此类资源的数量存在硬性限制,并且您要打开的此类资源的数量也差不多,那么如果您不处置,您很容易用完它们。
    • 实际上,如果您不调用Dispose,您最终可能会遇到托管内存仍然很空,但非托管资源已耗尽的情况。所以请尽快致电Dispose。一旦您不需要已定义该方法的对象,请调用它。
    • @MikeChristensen 这不太对。 Dispose(true) 应该只在其他托管对象上调用 Dispose。如果终结器正在运行,则 GC 当前正在处理 fReachable 队列。这意味着此时也会清理任何引用的非托管资源(这比我们想要的要晚)。只是不是通过 Dispose
    【解决方案3】:

    是的,使用using。这是一个很棒的声明。

    实际上,如果您不调用Dispose(手动或使用using),您最终可能会遇到托管内存仍然很空,但非托管资源已耗尽的情况。最终它可能会导致死锁,因为其他对象或其他进程将等待您的非托管资源,而您将等待它们。 (垃圾收集器不会运行,因为托管内存仍然不会满。)

    所以请尽快致电Dispose。一旦您不需要已定义该方法的对象,请调用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-22
      • 2013-07-21
      相关资源
      最近更新 更多