在.Net中完成的成本

时间:2010-06-15 13:55:11

标签: c# .net vb.net idisposable finalize

(1)我已经阅读了很多关于IDisposable的问题,其中答案建议不要使用Finalize,除非你真的需要因为涉及的处理时间。
我没有看到的是这笔费用是多少以及支付的频率。每毫秒?第二?小时,天等。

(2)此外,在我看来,如果一个物体可以处理,并不总是知道Finalize是否方便。例如,框架字体类。控件无法处理它,因为它不知道字体是否共享。字体通常是在设计时创建的,因此用户不会知道处理它,因此在没有引用的情况下最终确定踢出最终摆脱它。这是一个正确的印象吗?

5 个答案:

答案 0 :(得分:7)

finalize的主要问题是它阻止对象被垃圾回收。相反,调用终结器,并在“下次运行”时收集对象。好吧,从技术上讲IIRC终结器在一个单独的线程中运行一个对象列表。无论如何,这不是一个“每个ms”的问题,更多的是“需要多个GC运行才能摆脱对象。”

答案 1 :(得分:4)

Finalize在概念上与Dispose不同。 Finalize只能 免费的非托管资源。 Dispose可以释放托管和非托管资源。你应该适当地使用每个。 (请注意,具有Finalizer的类应始终实现IDisposable)。

必须明确调用Dispose; Finalize只能由GC调用。

更新:请参阅How to Implement IDisposable and Finalizers: 3 Easy Rules上的博文。

答案 2 :(得分:1)

答案 3 :(得分:1)

我会回答你的第二个问题。

不,Finalize不应以这种方式使用。事实上,除了极少数边缘情况之外,如果直接类拥有非托管资源,则只应覆盖Finalize(或在C#中声明析构函数)。

您描述的问题是所有权问题。 IDisposable类的所有者负责其生命周期以及何时致电Dispose的决定。代码的其他部分可以免费使用该类,但由于它们不能声明所有权,因此不应参与该类的生命周期管理。

不幸的是,我对Font类不太熟悉,也不知道它与你的问题推动的具体场景有什么关系,但我可以做一个可能适用于你的一般性陈述。如果您的代码没有直接创建实例(通过构造函数),那么您的代码不应被视为所有者。在这种情况下,您可以承担处理的责任留给其他人。

答案 4 :(得分:0)

Finalize作为双重检查非常有用。如果崩溃或某人的错误代码在超出范围之前没有处置您的对象,请保证其资源将在终结器中释放。

你可以通过调用GC.SuppressFinalize(this)来处理你的处理器中的一些花哨的步法,这将允许你编写一个在两种情况下都能工作的方法,并保证代码能很好地工作。

如果您正在编写一个框架来提醒人们他们应该丢弃您的对象,您甚至可以启动MDA。

终结器的惩罚基本上是你最终将对象推入2级队列,这需要更长的时间才能运行。如果你一直在使用对象并且他们正在最终确定这可能导致2级集合比必要的运行更频繁,只是为了运行你的终结器线程。