0

我有一个存在内存泄漏的 MVP 项目(它不是一个 Web 项目)。每次将数据从数据库加载到表单上的网格时,内存都会增加。我尝试使用 ANTS 和 .NET 内存分析器调查连接到该表单的每个对象。

打开/关闭表单时连接到表单的对象在 Instance Retention Graph 上如下所示:

A -> B : object1 标记在 ->; (参考资料) B -> A : object2 上的标记 ->; (引用)其中 A,B 是类

下一个方向是正确的方法吗?1. 在基类中实现来自msdn.comIDisposable的pattern1在每个未实现的 .cs 模块中;

  1. 在派生类中从 msdn 实现 pattern2(覆盖Dispose方法的类)
  2. 将一些清除对象/其他引用(object.property,object.other_field)的函数放在Dispose方法的“托管资源”部分中

  3. 当对象不再在该 .cs 中使用时,强制对象为 null 或 object.Dispose() (对每个 .cs 执行此操作?还是有其他方法)

我怎样才能强制所有这些方法和 GC 执行让我们明确地说在表单关闭时?

如果我从特定的 .cs 中删除对象就足够了吗?

谢谢

4

2 回答 2

1

IDisposable与垃圾收集或内存管理无关,或者至少不是直接的。MS对此有何评论:

该接口的主要用途是释放非托管资源。当不再使用该对象时,垃圾收集器会自动释放分配给托管对象的内存。

如果您的对象不包含非托管资源,则不应实现IDisposable,否则会给其他编码人员留下这样的印象。

如果要释放托管资源,只需断开主程序引用树与资源之间的链接即可。在这种情况下,如果您不再需要该表单,则释放它可能是一个非常简单的点。

MyForm = null;

或者,如果您只想释放表单内的资源,您可以在表单内的回调中破坏它们的引用。

protected void OnFormClose(object sender, EventArgs e)
{
    MyVeryFatObjectList = new List<object>();
}

如果由于某种原因您想显式调用垃圾收集器:

System.GC.Collect();

但是,请注意,不建议这样做。如果您正确地完成工作,GC 通常足够智能以正确地完成其工作。

于 2013-04-14T13:20:01.163 回答
0

从您的 A 引用 B、B 引用 A 上面的语句判断,我猜您有一个循环对象引用,它阻止垃圾收集清理您的引用。

垃圾收集会不时运行并清理不再引用的对象使用的内存。如果两个对象相互引用,那么它们将不会被清理。

您可以删除引用,只需购买将其值更改为 null。

发生这种事情的另一种方式,尤其是在 winforms 应用程序中,是通过事件处理程序,所以一旦你完成了它们,就解开你添加的任何事件处理程序。

实现 IDisposable 接口为您提供了一个很好的方法,您可以在其中放置所有清理代码并通知您的类的用户需要清理。您仍然需要确保直接或通过 using 语句调用 dispose 方法。

此外,如果您想以一种松散的方式保存对对象的引用,并且不会阻止它被垃圾收集,您可以使用Wea​​kReference,但大多数时候都不需要这样做。

于 2013-04-29T02:43:50.987 回答