2016-01-18 3 views
2

Я только новичок в C# и взял на себя проект на работе, который включает в себя код, внесенный другими разработчиками. При чтении данных из sql происходит утечка памяти. В основном код считывает результат ping из базы данных и возвращает его в искровую линию, которую я затем показываю на приборной панели. Надеюсь, ты поможешь.утечка памяти в C# чтение данных из базы данных sql

[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; 
     } 
    } 
+3

«* Там будет утечка памяти с кодом *» - как вы это обнаружить? На самом деле в управляемом приложении .NET нет никаких «чистых» утечек памяти. Конечно, вы можете столкнуться с тем, что ссылаются на управляемые объекты, не позволяя GC собирать их или в некоторых случаях не выпускать неуправляемые ресурсы). –

+0

с менеджером задач Windows (я понимаю, что использование этого не рекомендуется). Рабочий процесс IIS express начинает использовать память 80 МБ, а затем, когда результаты будут нарастать с течением времени, он может превышать 1000 МБ, пока я не удалю все строки в истории ответов, а затем вернется к 80 МБ. – qore5

+1

Попробуйте вместо этого проверить CLRProfiler. Вполне возможно, что ваша проблема вызвана фрагментацией памяти, например, - вы фиксируете много памяти в цикле, что, вероятно, предотвращает правильное уплотнение кучи. Не удалять объект 'сущности', как правило, не будут препятствовать подключению SQL-соединений до следующего GC, чего вы хотите избежать (используйте' using'). – Luaan

ответ

9

Я подозреваю, что Entities это класс, порожденный Entity Framework и унаследовал от DbContext. Если это так попробуйте использовать using блок:

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

Пожалуйста, обратите внимание, что в целом это не идеальное решение, чтобы начать новый экземпляр DbContext для каждого запроса. Подробнее см. this отличный ответ.

+0

хороший улов на неопределенный вопрос – user1666620

+0

Спасибо за помощь. Я добавил блок использования, как описано выше. Я все еще вижу, что память в службе IIS идет от 80 МБ (как только все данные очищаются в базе данных) до более 2000 МБ всего за пару дней. Цените больше помощи по этому поводу. – qore5

0

Вы можете попробовать сделать это:

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(""); 
    } 
Смежные вопросы