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

时间:2017-01-03 15:46:50

标签: c# memory telerik

我在Visual Studio 2017 RC中使用C#,。Net 4.6.x和Telerik控件进行WinForms。该应用程序包含一个" main"使用RadRibbon和RadPageView的窗口。 RadPageView是基于搜索表单(第一页)或请求新空白表单的用户动态填充的页面。其他页面继承自RadPageViewPage,并具有名为" TQC"的附加属性。 TQC指的是在页面上加载的自定义控件。

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

我遇到的问题是,当外部RadPageView Remove()是一个页面时,该页面占用的内存不会释放,大约为几百兆字节。这是有问题的,因为目标机器具有4GB到8GB的RAM。我尝试将填充控件的数据对象设置为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。

回应评论中的问题:

抛出错误的对象通常是相对随机的,取决于加载的帐户。它没有任何无限递归。这是控件最初加载的方式(使用特殊的连接类):

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;

    }

1 个答案:

答案 0 :(得分:0)

经过进一步调查,我能够理解这涉及Telerik如何加载其主题和控件。为下拉列表https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-14-04#prerequisites 创建所有数据源会减少占用空间,但每个选项卡中控件的主题管理器和主题每次都会加载为新的。通过设计,当控制器被关闭和处理时,它们不一定被设置。必须重新设计UI以防止用户内存不足。如果使用标准WinForms结合相同的设计,问题就会消失。