【发布时间】: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