C#内存并处理相关问题

时间:2009-12-23 21:22:11

标签: c# dispose

我有以下一段代码,只是想查看谁会调用处理?是自动调用。

ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, toolTipText);

另外,我要创建一个Timer局部变量,谁将调用dispose,内存泄漏怎么样,如果我立即调用dispose,则不会触发timer事件。

我是否需要确保调用timer事件处理程序dispose,即使我没有对timer变量的任何引用。我还需要取消注册该计时器的事件处理程序。

编辑:

  • 但如果我调用它,如何在ToolTip上调用dispose将无法显示。
  • 另外,如果我没有任何参考,我还需要配置计时器。
  • 我是否还需要取消注册计时器事件处理程序?
  • 同时保留引用会增加类内存占用量。

5 个答案:

答案 0 :(得分:6)

ToolTip在显示它的控件上注册事件处理程序。触发表单的Deactivate事件时会自动调用Hide()方法。表单关闭时会发生这种情况。这反过来确保其Windows句柄被销毁并且事件处理程序未注册。之后,没有剩余的一次性物品。

您可以使用Reflector或Reference Source自行验证。相关方法依次为BaseFormDeactivate,HideAllToolTips,Hide,ClearTopLevelControlEvents。

您不必调用Dispose(),也没有泄漏。

答案 1 :(得分:2)

Dispose是一种允许您立即释放对象的方法。例如,独占文件流。

Finalize是一种方法,一旦程序不再使用该对象,它就会自动释放该对象正在使用的任何资源。

当对象使用独占或有限资源时,您只需要担心处置。示例是文件一或数据库连接。 (注意,在这两种情况下,Close等同于处理)

要回答你的问题,你根本就不会处理,而是在需要时让终结器运行。

答案 2 :(得分:1)

你需要在任何实现IDisposable的东西上调用Dispose,或者至少确保一些东西。对于UI组件,将它们添加到表单的Controls集合中,当表单关闭时它们将被释放。对于其他事情,您需要保留对它们的引用并适当地调用dispose。使您的类实现IDisposable可能适合在组合对象上调用Dispose。

答案 3 :(得分:1)

在.NET中,当无法再从任何地方引用对象时,垃圾收集器将自动释放内存。当它这样做时,如果对象有一个终结器,它会调用终结器。终结器用于清理,通常是非托管资源。

但是,终结器很昂贵(例如,它们延迟了对象的垃圾收集),你无法确定它何时运行(因为你无法判断GC什么时候决定收集它)。它们通常被用作清理非托管资源等物品的最后手段。

这是IDisposable接口及其Dispose方法的用武之地.Dispose也可用于清理托管和非托管资源。当您调用Dispose方法时,它会清理并且对象不再处于稳定,可用的状态。

如果您有一个实现IDisposable的资源,您可以在知道完成后调用Dispose。它所持有的方式和资源可以尽快释放出来。执行此操作的常用方法是将其包装在using语句中,该语句将在using块完成时自动Dispose。 e.g:

using (SomeDisposableObject disposableObject = new SomeDisposableObject())
{
     disposableObject.DoSomeStuff();
     disposableObject.DoSomeMoreStuff();
}

当使用块完成时(在DoMoreStuff之后)在disposableObject上调用Dispose。在考虑异常处理时,使用语句比等效代码更清晰。

对于像ToolTip这样的东西,它有非托管引用(很多WinForms在非托管Win32组件的包装中),它将有一个终结器,可以确保正确释放未管理的资源。但是,如果在对象上调用Dispose,则会在那里运行清理代码,然后终止终结器(当GC收集对象时,它将不会运行。)

因此,要更直接地回答您的问题,如果您确切知道IDisposable何时完成,最好调用Dispose。但是,如果不这样做,通常只需将其留给垃圾收集器来收集它并调用相关代码来正确清理对象。

在给出ToolTip和Timer的情况下,我不担心自己调用Dispose,因为我怀疑很难预测它们什么时候完成。

答案 4 :(得分:0)

通常,由注册到事件的对象取消注册 - 不这样做会造成内存泄漏。你不应该依赖Dispose方法。

除非您将对象包装在using(){}语句中,否则不会自动调用Dispose,也不会将其添加到对象IContainer实例(如果它是设计器类)。如果它是一个类变量,则需要使包含类实现IDisposable并在其中处理实例。