解决 OutOfMemoryException 的最佳方法? (C#)

Best way to resolve OutOfMemoryException? (C#)

我在 Visual Studio 2017 RC 中使用 C#、.Net 4.6.x 和用于 WinForms 的 Telerik 控件。该应用程序由使用 RadRibbon 和 RadPageView 的 "main" window 组成。 RadPageView 根据第一页的搜索表单动态填充页面,或者由用户请求新的空白表单。其他页面继承自 RadPageViewPage,并有一个额外的 属性,称为 "TQC"。 TQC 是指在页面上加载的自定义控件。

TQC 在 RadPageViewPages 中有几个下拉列表和文本区域,它们都包含在 TQC 对象内的 RadPageView 控件中。它不会将任何数据绑定到它的控件,直到它的 RPVP(class 继承 RadPageViewPage)被选中。其中一个下拉列表在填充时包含 200 个左右的条目(帐户列表)。

我遇到的问题 运行 是当外部 RadPageView Remove() 页面时,该页面占用的内存没有释放,大约为几百兆字节。这是有问题的,因为目标机器有 4GB 到 8GB 的​​内存。我尝试将填充控件的数据对象设置为 null 作为关闭事件的一部分,但没有任何改变。我还尝试对 RadPageViewPage 的所有后代显式调用 Dispose() 方法,如下所示:

private void rpvQtabs_PageRemoved(object sender, RadPageViewEventArgs e)
    {

        foreach (TQC c in e.Page.Controls)
        {                
            foreach (Control ca in c.Controls)
            {
                foreach (Control cac in ca.Controls)
                {
                    cac.Dispose();
                }
                ca.Dispose();
            }
            c.Dispose();
        }
        e.Page.Dispose();           
    }

我仍然遇到疯狂的巨大内存泄漏,如果用户查看了 5 个以上的选项卡(即使他们关闭了页面),很快就会出现 OutOfMemoryException。我尝试附加 Performance Profiler,但它在尝试时崩溃了。 VS 2015 目前不是一个选项。如何确保页面得到正确处理,或减少超大下拉列表的内存占用?这是我们第一次尝试使用 Telerik。

回复评论中的问题:

引发错误的对象通常是相对随机的,取决于加载了哪些帐户。这不是无限递归的东西。这是最初加载控件的方式(使用特殊连接 class):

public static List<Account> List(bool includeDefaults = true)
    {
        //search
        var rs = new List<Account>();
        string q = "select distinct r.ID, r.name from db.addressbook r";
        DataTable dt = new DataTable();
        using (var cmd = new CustomConnectionClass())
        {
            cmd.Safety.Off();
            dt = cmd.ExecuteDirectQuery(q);
        }

        foreach (DataRow r in dt.Rows)
        {
            var a = new Account();
            a.ID = long.Parse(r[0].ToString());
            a.Name = r[1].ToString();
            rs.Add(a);
        }
        rs = rs.OrderBy(t => t.ID).ToList();
        var n = new Account();
        n.ID = 0;
        n.Name = "Generic Account";
        var o = new Account();
        o.ID = 999999;
        o.Name = n.Name;
        rs.InsertRange(0, new Account[] { n, o });
        return rs;

    }

经过进一步调查,我能够弄清楚这涉及到 Telerik 如何加载其主题和控件。使下拉列表的所有数据源 static 减少了一点占用空间,但每个选项卡中控件的主题管理器和主题每次都加载为新的。根据设计,当控件关闭和释放时,它们不一定被释放。 UI 的设计必须重新设计以防止用户 运行 内存不足。如果使用标准 WinForms 合并相同的设计,问题就会消失。