【问题标题】:memory leak in c# reading data from sql databasec#从sql数据库读取数据中的内存泄漏
【发布时间】:2016-01-18 14:28:06
【问题描述】:

我只是 C# 的初学者,并且已经接手了一个项目,其中包括由其他 2 位开发人员贡献的代码。从 sql 读取数据时,代码存在内存泄漏。基本上,代码从数据库读取 ping 结果并将其返回到迷你图中,然后我将其显示在仪表板上。希望你能帮忙。

[ActionName("get-response-times")]
    public JsonResult GetResponseTime()
    {
        try
        {
            //todo...get list of sites we we want to check from database
            var entities = new Entities();

            var sites = entities.Sites.ToList();

            var status = new List<ResponseDataModel>();

            foreach (var site in sites)
            {
                var response = Ping(site.URL);

                site.SiteResponseHistories.Add(new SiteResponseHistory
                {
                    CreateDate = DateTime.UtcNow,
                    ResponseTime = (int)response,
                    Site = site
                });

                status.Add(new ResponseDataModel
                {

                    ResponseTime = (int)response,
                    Name = site.Name,
                    ID = site.Id,
                    History = site.SiteResponseHistories.OrderByDescending(a => a.CreateDate).Select(a => a.ResponseTime.GetValueOrDefault(0)).Take(100).Reverse().ToArray()
                });
            }

            entities.SaveChanges();

            return Json(status);
        }
        catch (Exception)
        {
            // handle if necessary
        }

        return Json("");
    }

    protected long Ping(string url)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Timeout = 3000;
            request.AllowAutoRedirect = false; // find out if this site is up and don't follow a redirector
            request.Method = "HEAD";

            Stopwatch watch = new Stopwatch();

            watch.Start();

            using (var response = request.GetResponse())
            {
                return watch.ElapsedMilliseconds;
            }
        }
        catch
        {
            return -1;
        }
    }

【问题讨论】:

  • "代码存在内存泄漏" - 您是如何检测到的?实际上,在 .NET 托管应用程序中不存在“纯”内存泄漏(当然,您可能会遇到持有对托管对象的引用阻止 GC 收集它们或在某些情况下无法释放非托管资源的情况)。
  • 用windows任务管理器,(我明白使用这个是不可取的)。 IIS express 工作进程开始使用 80MB 内存,然后随着时间的推移结果逐渐增加,它可以运行超过 1000MB,直到我删除响应历史记录中的所有行,然后它又回到 80MB。
  • 尝试使用 CLRProfiler 检查。例如,您的问题很可能是由内存碎片引起的 - 您将大量内存固定在一个循环中,这可能会阻止正确的堆压缩。不释放 entities 对象会使 SQL 连接悬空,直到下一次 GC,这是您想要避免的(使用 using)。
  • 注意:.Net 中的自动垃圾收集部分取决于系统有多少可用内存——如果有足够的可用内存,这种情况发生的频率会降低。仅观察高内存使用率本身并不是泄漏的证据。

标签: c# sql visual-studio


【解决方案1】:

我怀疑Entities是Entity Framework生成的类,继承自DbContext。如果是这样,请尝试使用using 块:

using(var entities = new Entities())
{
    ...
    entities.SaveChanges();
}

请注意,一般来说,为每个请求启动 DbContext 的新实例并不是完美的解决方案。详情见this很好的回答。

【讨论】:

  • 感谢所有帮助。我如上所述添加了 using 块。我仍然看到 IIS 服务上的内存在短短几天内从 80mb(一旦数据库中的所有数据被清除)增加到超过 2000mb。感谢您对此的更多帮助。
【解决方案2】:

您可以尝试这样做:

    using (var context = new Context()) 
{     
    // Perform data access using the context 
}

你的代码是这样的:

        [ActionName("get-response-times")]
    public JsonResult GetResponseTime()
    {
        try
        {
            var status = new List<ResponseDataModel>();
            //todo...get list of sites we we want to check from database
            using (var entities = new Entities())
            {
                var sites = entities.Sites.ToList();

                foreach (var site in sites)
                {
                    var response = Ping(site.URL);

                    site.SiteResponseHistories.Add(new SiteResponseHistory
                    {
                        CreateDate = DateTime.UtcNow,
                        ResponseTime = (int)response,
                        Site = site
                    });

                    status.Add(new ResponseDataModel
                    {

                        ResponseTime = (int)response,
                        Name = site.Name,
                        ID = site.Id,
                        History = site.SiteResponseHistories.OrderByDescending(a => a.CreateDate).Select(a => a.ResponseTime.GetValueOrDefault(0)).Take(100).Reverse().ToArray()
                    });
                }

                entities.SaveChanges();
            }
            return Json(status);
        }
        catch (Exception)
        {
            // handle if necessary
        }

        return Json("");
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 2014-04-29
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多