在c#中,我们可以使用finalize来配置托管源吗?

时间:2013-07-11 06:16:27

标签: c# garbage-collection dispose finalize

根据如何使用IDisposable的模式,Microsoft建议使用finalize来释放非托管源。 http://msdn.microsoft.com/en-us/library/system.idisposable%28v=VS.80%29.aspx

但是如果我们编写一些代码来在最终版本中发布托管源代码会怎样? 也就是说当GC调用最终确定释放一些托管源时,会发生什么?

5 个答案:

答案 0 :(得分:3)

一般来说是一种不好的做法。在终结器代码中,您不能依赖于对象的状态及其受管资源 - 它们可以被收集或处理/最终确定。此外,您不能依赖CLR调用Finalize的订单。

答案 1 :(得分:1)

通常,使用Finalize清理外部受管资源是没用的,可能很危险。当对象终结器运行时,它所拥有的托管资源可能是:

  1. 由于他们的终结器已经运行已经清理过,在这种情况下处理它们将是无用的。
  2. 尚未清理,但被任何活动对象识别为未被引用,在这种情况下,无论当前正在执行的终结器是否尝试清除它们,它们的终结器都将在适当的时候运行。
  3. 仍在使用其他活动对象,在这种情况下,它们不应由当前运行的终结器清理。

在某些情况下,让终结器在其他托管对象上调用清理代码可能会有所帮助,但这种调用通常仅适用于对象了解彼此内部详细信息的情况,并且通常应使用{ {1}}或protected方法,或使用私下交换的代理。例如,在某些情况下,可能存在两个或多个彼此了解的对象,并且具有必须以特定顺序运行的终结器。

例如,可能有一个类的目的是将数据发送到USB设备,另一个类的目的是控制连接到该设备的设备。如果后一类想要确定设备接收到“关闭”命令,则在USB连接类终结器关闭连接之前,其终结器可能需要发送命令。处理这个问题最干净的方法可能是让USB连接对象的构造函数接受它将从其终结器调用的回调。如果班级没有这样的功能,事情就会变得相当棘手。另一种方法可能是让一个对象与包装器分开,它包含清理所需的所有信息,以及包装器对象的internal,并且有一个timer-tick事件,如果WeakReference将执行清理已经死了。如果计时器绑定到创建包装器对象的线程,那么即使放弃了包装器对象,也可以允许执行清理,前提是线程仍处于活动状态(如果它可能不存在,事情会变得更复杂)。

答案 2 :(得分:0)

看看这个链接,你可以使用Finalize

http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.71).aspx

答案 3 :(得分:0)

为什么(或更好,如何)发布在终结器中管理的内容?当前对象拥有的所有内容此时已被视为垃圾,并将在下一次垃圾收集器中收集。当前拥有的所有内容都无法释放,因为其他内容可能仍会引用它。

答案 4 :(得分:-1)

无需为托管代码编写Dispose / Finalize。 bcz当对象不再被引用时它将被CLR删除。 Dispose方法是针对非托管代码编写的,如文件处理程序或数据库命令。

相关问题