如何释放占用的内存

我的项目中有一个主窗口,主窗口中还有许多其他的子窗口。
我注意到。 当我打开主窗口占用内存1500K时,打开一个子窗口时就增加了占用内存6000K。
当我打开第二个窗口做同样的事情。 当我closures两个子窗口时,占用的内存不会被释放。
所以我想要的是当我closures子窗口时释放占用的内存。
我怎么能做到这一点?
如果可能的话,请在vb.net中给我一些代码示例。
这个问题经常在Local NET上的计算机上而不是在我的计算机上(开发人员计算机上有SQL服务器)。

按照Pranay的建议使用默认情况下会调用Dispose方法。 否则显式地你必须在你的子窗体上调用this.close()之后调用this.dispose()。 但是请确保你在关闭后不会使用子表单元素或值。 由于处置将最终清除一切。

处理非托管资源的MSDN示例

Imports System Imports System.ComponentModel ' The following example demonstrates how to create ' a resource class that implements the IDisposable interface ' and the IDisposable.Dispose method. Public Class DisposeExample ' A class that implements IDisposable. ' By implementing IDisposable, you are announcing that ' instances of this type allocate scarce resources. Public Class MyResource Implements IDisposable ' Pointer to an external unmanaged resource. Private handle As IntPtr ' Other managed resource this class uses. Private component As component ' Track whether Dispose has been called. Private disposed As Boolean = False ' The class constructor. Public Sub New(ByVal handle As IntPtr) Me.handle = handle End Sub ' Implement IDisposable. ' Do not make this method virtual. ' A derived class should not be able to override this method. Public Overloads Sub Dispose() Implements IDisposable.Dispose Dispose(True) ' This object will be cleaned up by the Dispose method. ' Therefore, you should call GC.SupressFinalize to ' take this object off the finalization queue ' and prevent finalization code for this object ' from executing a second time. GC.SuppressFinalize(Me) End Sub ' Dispose(bool disposing) executes in two distinct scenarios. ' If disposing equals true, the method has been called directly ' or indirectly by a user's code. Managed and unmanaged resources ' can be disposed. ' If disposing equals false, the method has been called by the ' runtime from inside the finalizer and you should not reference ' other objects. Only unmanaged resources can be disposed. Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) ' Check to see if Dispose has already been called. If Not Me.disposed Then ' If disposing equals true, dispose all managed ' and unmanaged resources. If disposing Then ' Dispose managed resources. component.Dispose() End If ' Call the appropriate methods to clean up ' unmanaged resources here. ' If disposing is false, ' only the following code is executed. CloseHandle(handle) handle = IntPtr.Zero ' Note disposing has been done. disposed = True End If End Sub ' Use interop to call the method necessary ' to clean up the unmanaged resource. <System.Runtime.InteropServices.DllImport("coreel32")> _ Private Shared Function CloseHandle(ByVal handle As IntPtr) As [Boolean] End Function ' This finalizer will run only if the Dispose method ' does not get called. ' It gives your base class the opportunity to finalize. ' Do not provide finalize methods in types derived from this class. Protected Overrides Sub Finalize() ' Do not re-create Dispose clean-up code here. ' Calling Dispose(false) is optimal in terms of ' readability and maintainability. Dispose(False) MyBase.Finalize() End Sub End Class Public Shared Sub Main() ' Insert code here to create ' and use the MyResource object. End Sub End Class 

(更新检查]

如果你的孩子的表格有签名。 这些默认添加到表单。

 'Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 

对这个问题的其他一些答案包含了令人失望的错误信息,而另一些答案却使问题大大过度复杂化。 在.NET中围绕垃圾回收存在很多误解,这里所讲的理论当然不能解决问题。

首先,使用Windows任务管理器分析内存使用情况是一个巨大的错误 。 你会得到严重的无效信息 ,试图根据这些信息修改你的应用程序只会让事情变得更糟,而不是更好。 如果您怀疑存在性能问题(大多数应用程序确实会遇到任何问题,这是非常令人怀疑的),您需要投资一个合适的内存分析器并使用它。

其次,垃圾收集的关键在于你不必担心这种事情 你不但不必担心,而且你也不必担心。 编写面向.NET Framework的应用程序时,您不应该进行任何类型的手动内存管理。 抵制诱惑与垃圾收集器的内部工作,当任何人告诉你调用GC.Collect手指强制垃圾收集发生时,将你的手指牢牢地GC.Collect你的耳朵。 我想我不应该说从来没有,但几乎没有理由这样做。 我更可能怀疑手动调用垃圾回收的代码。

为什么不应该手动调用垃圾回收? 那么,除了这个显而易见的论点,它首先破坏了使用托管语言的全部观点,这是因为垃圾收集是一个艰巨而缓慢且昂贵的过程 为了保持最佳性能,您希望它尽可能地运行。 幸运的是,执行垃圾收集算法的程序员比你或我更聪明,更有经验:他们设计了它只在必要时运行,而不是经常这样。 你不会看到更经常运行的优势,但是你看到一个劣势。 对于程序员来说,这应该是完全不透明的。

唯一的例外是当您使用非托管对象时,这些对象不由垃圾收集器收集或管理。 您将能够识别这些对象,因为它们都实现了IDisposable接口 ,它提供了Dispose方法来释放非托管资源。 在公开此方法的对象上,您应该在完成对象的使用后立即调用它。 或者更好的做法是,在using语句中声明和使用对象, 无论发生什么事情 (即使在使用对象的代码中抛出异常),它都会自动处理对象。

当然,您会注意到Windows窗体库中的几个标准对象实现了IDisposable方法。 无处不在的Form类 ,例如,提供了一个Dispose方法。 但是,这并不意味着您有责任手动处理这些对象。 一般来说,你只需要明确地调用Dispose方法来显式地创建对象,对吗? 框架自动创建的对象也被框架自动销毁。 例如,在设计时放置在Form对象上的控件在处理容器表单时会自动处理。 并且Form对象在关闭时自动处理。 这与你提出的问题特别有关。 Form.Close方法的文档告诉我们这个:

当表单关闭时,关闭对象内创建的所有资源,并处理表单。

[。 ]

当一个表单没有处于Close状态时的两个条件是:(1)它是多文档界面(MDI)应用程序的一部分,并且表单不可见; 和(2)你已经使用ShowDialog显示了表单。 在这些情况下,您需要手动调用Dispose来标记垃圾收集的所有表单控件。

请注意,一般来说,您不会发现自己必须从代码手动调用Form.Dispose 当MDI父Form.Dispose不可见时,用户不可能关闭MDI子窗体,而且如果您碰巧在代码中当父Form.Dispose不可见时自己关闭窗体,则可以直接插入对Form.Dispose的调用。 当您使用ShowDialog方法将窗体显示为模式对话框时,您可以方便地将其创建和使用包含在using语句中。

现在回想一下,仅仅在一个对象上调用Dispose方法只会释放非托管资源,并将该对象标记为可用于垃圾回收。 它不会立即释放该对象声明的内存。 这一点很重要,因为这正是你在内存分析方面的尝试所关注的。 你知道这些对象正在被处置,因为你提到变量对你来说不可用(你说你“失去了它们的价值”)。 这是因为你不能访问处理的对象。 然而,这并不意味着他们声称的内存已经完全释放。 这样做的垃圾收集器的工作,我们已经建立了你不应该猴子。 它将等待释放内存,直到应用程序空闲,或迫切需要重用该内存。 否则,它会推迟收集, 这还行

利用使用块,这会自动释放内存

 Using { resourcelist | resourceexpression } [ statements ] End Using 

这就是你不应该关心的。

.NET Framework 垃圾收集器将为您完成这项工作。

.NET Framework的垃圾收集器管理应用程序的内存分配和释放。 每次创建新对象时,公共语言运行库都会为托管堆中的对象分配内存。 只要地址空间在托管堆中可用,运行时就会继续为新对象分配空间。

编辑

你必须确保你没有使用你自由的资源了。 垃圾收集器的功能位于名称空间System下的GC类中。

为了调用它,你可以做GC.Collect() ,虽然我建议你阅读更多关于这个主题,并看到像这样的一些例子

垃圾收集器会为你做的工作,所以你真的不应该介意。 如果且仅当您使用非托管资源时(com interop / PInvoke),您应该有更深入的了解。

我不是VB.net的专家,但据我所知它有一个垃圾收集器。 这通常意味着关闭子窗口不会释放内存,但如果删除对子窗口的所有引用,则垃圾收集器可能会在下次运行时释放它。

另外,你通常可以“询问”垃圾收集器运行,但通常它自己“决定”什么时候运行。

您可以使用其中一个可用的内存分析器,例如ANTS Memory Profiler(查看使用ANTS Memory Profiler来追踪WinForms应用程序中的内存泄漏 )。 您也可以使用WinDbg,但没有经验,它会比专门的工具更复杂。

常见的“内存泄漏”原因之一是添加“外部”事件处理程序形成(例如对于静态或长寿命对象),而不是删除形式破坏,所以GC“认为”你有形式参考,而不是收集其数据。

为什么以及如何避免事件处理程序内存泄漏?

.NET内存泄漏案例研究:制造内存Baloon的事件处理程序

垃圾收集基础

处置,定稿和资源管理

如何识别公共语言运行库中的内存泄漏

如何检测和避免.NET应用程序中的内存和资源泄漏