【问题标题】:Is it possible to determine an object being disposed right after last object reference freed up?是否可以确定在最后一个对象引用释放后立即处理的对象?
【发布时间】:2014-11-26 15:14:02
【问题描述】:

我正在创建一个环绕堆对象的内存持有者类,我想 确定对象的dispose对于GC来说是很给力的。

我想要类似的东西:

myObj = null; //Immediately call to ~myObj()

【问题讨论】:

  • 终结器不会被确定性地调用。您可以使用GC.Collect 强制GC,但这将强制GC 运行- 这是一个严重的惩罚- 不要这样做(我提出它是因为有人可能会推荐它)。它甚至不能保证您已经设法删除了对该对象的所有强引用。您正在尝试做的事情与 .NET Framework 的一些设计理念非常矛盾。我会尝试找出一种方法来遵循这些哲学,而不是反对它们。
  • 我可以创建一个 COM 对象吗?是否删除了最后调用的 IUnknown.Release 强引用?
  • 我知道,但我正在一个小型库中创建我的 Memory 类供初学者使用,我希望他们对内存垃圾回收不做任何事情。
  • 帮您的初学者一个忙,教他们管理昂贵资源的正确方法:using/IDisposable
  • 如果你定义了一个终结器~myObj(),那么你“可能做错了什么”。您应该询问有关您的实际要求的问题,以便我们以不需要您创建(或使用)终结器的方式为您提供帮助。

标签: c# .net garbage-collection destructor


【解决方案1】:

.NET 框架和运行时为使用非托管资源的应用程序提供了两个功能。

  1. 确定性清理IDisposable 接口允许代码通过显式或隐式调用Dispose() 方法在特定时间释放资源。 (C# 中的 using 语句为该调用提供了隐式支持。)
  2. 最终清理:如果用户未能通过调用Dispose() 方法释放非托管资源,则可以使用终结器来防止长时间运行的应用程序随着时间的推移泄漏这些资源。用户代码通常不应包含用户定义的终结器;相反,创建(或使用现有的)扩展 SafeHandle 的类并实现 ReleaseHandle 方法来定义释放行为。

请注意,IDisposable.Dispose()唯一支持的确定性资源清理机制。最终清理是应避免的非确定性回退。

【讨论】:

    【解决方案2】:

    不,你不能这样做。您应该简单地使用IDisposable,因为它应该被使用。

    【讨论】:

    • 好的,我明白了! ,但我可以创建一个 COM 对象吗?是否删除了最后调用的 IUnknown.Release() 强引用?
    • 我对 COM 对象不太熟悉,但我假设您可以在 Dispose 方法中调用 IUnknown.Release()。使用Dispose(bool) 方法注意msdn.microsoft.com/en-us/library/system.idisposable.aspx 中托管和非托管资源的模式。
    【解决方案3】:

    COM 对象在超出范围时希望得到及时通知,但 .NET 不支持提示通知,除非通过 Dispose。你应该在你的 dispose 方法中调用IUnknown.Release但是你必须在调用IUnknown.Release 之前确保没有任何人可以再次尝试使用该COM 对象。尝试使用具有 Release 之后的 COM 对象,或者甚至只是尝试再次调用 Release,都是灾难的根源。

    因此,我建议不要将对 COM 对象本身的引用发布给外部代码。相反,让持有对象的类将所有请求转发到锁内的对象本身(以确保代码不会尝试同时访问),并让您的 Dispose 方法获取锁,在对象上调用 Release ,然后使引用无效。任何未来尝试操作未被捕获的对象都会导致 NullReferenceException 不是很出色,但仍然比在释放后尝试使用 COM 对象要好。

    【讨论】:

      猜你喜欢
      • 2012-11-05
      • 2013-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-15
      • 1970-01-01
      相关资源
      最近更新 更多