C#记忆和处理相关问题

C#记忆和处理相关问题,c#,dispose,C#,Dispose,我有下面的代码,只是想检查谁将调用dispose?它是自动调用的 ToolTip toolTip = new ToolTip(); toolTip.SetToolTip(button, toolTipText); 另外,假设我创建了一个计时器局部变量,它将调用dispose,那么内存泄漏呢,因为如果我立即调用dispose,计时器事件将不会被触发 我是否需要确保在计时器事件处理程序中调用dispose,即使我没有任何对计时器变量的引用。我还需要注销该计时器的事件处理程序 编辑: 但是如何在工

我有下面的代码,只是想检查谁将调用dispose?它是自动调用的

ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, toolTipText);
另外,假设我创建了一个计时器局部变量,它将调用dispose,那么内存泄漏呢,因为如果我立即调用dispose,计时器事件将不会被触发

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

编辑:

  • 但是如何在工具提示上调用dispose,如果我调用它,它将不会显示
  • 还有,如果我没有任何参考资料,为什么我需要处理计时器
  • 我是否还需要注销计时器事件处理程序
  • 保留引用也会增加类内存占用

通常,由对象注册到要取消注册的事件-不这样做会造成内存泄漏。您不应该依赖Dispose方法来执行此操作


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

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

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

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


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

您需要对任何实现IDisposable的东西调用Dispose,或者至少确保有东西可以。对于UI组件,将它们添加到窗体的控件集合中,当窗体关闭时,它们将被释放。对于其他事项,您需要保留对它们的引用,并适当地调用dispose。使您的类实现IDisposable可能是适当的,只需在您的组合对象上调用Dispose即可。

工具提示在显示它的控件上注册事件处理程序。当窗体的Deactivate事件触发时,会自动调用它的Hide()方法。这将在窗体关闭时发生。这进而确保其Windows句柄被销毁,事件处理程序被注销。在那之后,就没有一次性物品了

您可以使用反射器或参考源亲自验证这一点。相关方法依次为BaseFormDeactivate、HidealToolTips、Hide、ClearTopLevelControlEvents


您不必调用Dispose(),也不会发生泄漏。

在.NET中,当对象无法从任何位置引用时,垃圾收集器将自动释放内存。执行此操作时,如果对象具有终结器,则调用终结器。终结器用于清理通常为非托管的资源

但是,终结器代价高昂(例如,它们会延迟对象上的垃圾收集),并且您无法知道何时运行终结器(因为您无法知道GC何时决定收集终结器)。它们通常是清理非托管资源之类的东西的最后手段

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

如果您有一个实现IDisposable的资源,您可以在知道完成后对其调用Dispose。这样一来,它所持有的资金和资源可以尽快释放出来。通常的方法是将其封装在using语句中,当using块完成时,该语句将自动进行处理。e、 g:

using (SomeDisposableObject disposableObject = new SomeDisposableObject())
{
     disposableObject.DoSomeStuff();
     disposableObject.DoSomeMoreStuff();
}
当使用块完成时(在domorteuff之后),对disposableObject调用Dispose。在考虑异常处理时,使用语句比等效代码干净得多

在类似ToolTip的情况下,它有非托管引用(在非托管Win32组件的包装中有许多WinForms),它将有一个终结器来双重确保正确释放未更改的资源。但是,如果在对象上调用Dispose,清理代码会在那里运行,并且终结器会被抑制(当GC收集对象时,它不会运行)

所以,为了更直接地回答您的问题,如果您确切地知道IDisposable何时完成,那么最好调用Dispose。但是,如果不这样做,通常可以让垃圾收集器来收集并调用相关代码来正确清理对象


对于给定的工具提示和计时器,我不担心自己调用Dispose,因为我怀疑很难预测它们何时完成。

我不同意,为什么要保留不必要的引用,请参阅问题中的编辑。您不需要调用
Dispose()
如果您满足于在完成过程中释放的资源(垃圾收集时间)。您可以保留(相对)廉价的引用,以避免保留(相对)稀缺或昂贵的资源。WinForms控件和组件实现IDisposable(因为它们保存有限的资源,如HWND或计时器句柄)因此应该被处理,而不是等待最终定稿人。但我应该担心保留引用和处理,还是让最终定稿人来完成这项工作。保留引用也会增加类内存占用。保留引用会增加类内存占用几个字节。但是这个类是Windows窗体,对吗?除非你想创造一百个