C# 在C语言中实现大型MVP项目的IDisposable#

C# 在C语言中实现大型MVP项目的IDisposable#,c#,memory-leaks,dispose,C#,Memory Leaks,Dispose,我有一个MVP项目存在内存泄漏(它不是一个web项目)。每次将数据从数据库加载到表单上的网格时,内存都会增加。我试着用ANTS和.NET内存分析器调查每个连接到表单的对象 打开/关闭表单时连接到表单的对象在实例保留图上如下所示: A->B:object1标记在->上;(参考文献) B->A:object2标记在->上;(引用人) 其中A,B是类 下一个方向是正确的方法吗? 1.在基类中实现未实现的每个.cs模块中的IDisposablepattern1 在派生类中实现msdn中的pattern2

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

打开/关闭表单时连接到表单的对象在实例保留图上如下所示:

A->B:object1标记在->上;(参考文献) B->A:object2标记在->上;(引用人) 其中A,B是类

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

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

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

  • 我如何强制所有这些方法和GC在表单关闭时显式执行呢

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


    谢谢

    IDisposable
    不是垃圾收集或内存管理,至少不是直接的。MS对此的看法:

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

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

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

    MyForm = null;
    
    或者,如果只想释放表单内的资源,可以在表单内的回调中断开它们的引用

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

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

    根据你的A引用B,B引用上面的一条语句判断,我猜你有一个循环对象引用,它阻止垃圾收集清理你的引用

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

    只需将引用的值更改为null,就可以删除引用

    这种事情发生的另一种方式,特别是在winforms应用程序中,是通过事件处理程序,因此在完成添加事件处理程序后,请将其取消挂钩

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


    此外,如果您希望以一种松散的方式保存对对象的引用,而这种方式不会阻止对象被垃圾收集,则可以使用,但这在大多数情况下并不需要。

    Dispose()
    主要是关于资源管理,而不是关于内存泄漏。所以不,这不是正确的方向。看看你是如何管理所有权的(引用的生存期)。你在表单上加载了多少数据到这个网格中?好的,是的,我知道我还应该调查其他元素
    @Henk Holterman
    ;我希望释放对表单sa的引用,以便GC最终能够清理内存。我还观看了很多升级到gen2的大型对象,但它们是程序运行所必需的。我还观看了LOH,对象只使用了大约10mb。碎片化有时很常见,并不总是能说明确切的问题
    @Henk Holterman
    @Mpn您可以在屏幕上显示2gb的数据。它来自数据库,使用Telerik mapping@Magnusso I just>对每个对象进行映射并将其设置为空?以及所有与数据库接触的对象?这是如何打破他们的参考@LightStriker@MPN:为什么是foreach?为什么不简单地重新初始化列表/表/数组<代码>MyList=新列表()?只要您在某个地方断开引用链,链中的任何对象及其引用都将被收集;我也应该用其他形式来做,不是吗?我从探查器中知道这些对象@你很可能在某个地方有一个瓶颈;存在大量数据的位置,在单个点中引用。例如,那些消耗大量内存的对象,可能在某种列表或表中引用,对吗?除非您告诉我您的数据在代码中的多个位置被引用?所以要释放非托管资源,我必须找到并释放与数据库连接的对象,并使用
    表单文件(或MemoryStream、FileStream),对吗@闪电射手
    
    System.GC.Collect();