2010-09-10 9 views
0

Я уже задал этот вопрос без ответа. Может ли кто-нибудь помочь? Я профилирую код ниже внутри синглтона и обнаружил, что много объектов Rate (List<Rate>) хранятся в памяти, хотя я их очищаю.Возможная утечка памяти в одноэлементном режиме?

protected void FetchingRates() 
{ 
    int count = 0; 

    while (true) 
    { 
    try 
    { 
     if (m_RatesQueue.Count > 0) 
     { 
     List<RateLog> temp = null; 

     lock (m_RatesQueue) 
     { 
      temp = new List<RateLog>(); 
      temp.AddRange(m_RatesQueue); 
      m_RatesQueue.Clear(); 
     } 

     foreach (RateLog item in temp) 
     { 
      m_ConnectionDataAccess.InsertRateLog(item); 
     } 

     temp.Clear(); 
     temp = null; 
     } 
     count++; 
     Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["RatesIntreval"].ToString())); 
    } 
    catch (Exception ex) 
    { 
     Logger.Log(ex);     
    } 
    } 
} 

Вставка в очередь производится:

public void InsertLogRecord(RateLog msg) 
{ 
    try 
    { 
    if (m_RatesQueue != null) 
    { 
     //lock (((ICollection)m_queue).SyncRoot) 
     lock (m_RatesQueue) 
     { 
     //insert new job to the line and release the thread to continue working. 
     m_RatesQueue.Add(msg); 
     } 
    } 
    } 
    catch (Exception ex) 
    { 
    Logger.Log(ex); 
    } 
} 

Рабочий вставляет журнал скорости в БД следующим образом:

internal int InsertRateLog(RateLog item) 
    { 
     try 
     { 
      SqlCommand dbc = GetStoredProcCommand("InsertRateMonitoring"); 
      if (dbc == null) 
       return 0; 
      dbc.Parameters.Add(new SqlParameter("@HostName", item.HostName)); 
      dbc.Parameters.Add(new SqlParameter("@RateType", item.RateType)); 
      dbc.Parameters.Add(new SqlParameter("@LastUpdated", item.LastUpdated)); 
      return ExecuteNonQuery(dbc); 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(ex); 
      return 0; 
     } 
    } 

Любой видит возможную утечку памяти?

+0

Можете ли вы переформатировать это, так что код проще увидеть, пожалуйста? –

+4

Я не знаю про утечки памяти, но, как вы «обрабатываете» исключения, крайне подозрительно начинать с. –

+0

Обратите внимание, что все исключения регистрируются в файловой системе с помощью общего регистратора. коды кода для него были удалены. – user437631

ответ

2

Похоже, вы не утилизацией SqlCommand, который висит на RateLog.

+0

Решено.Спасибо! утилита SqlCommand помогла ... – user437631

0

Как насчет перемещения temp создания вне цикла. Вероятно, вы не можете очистить GC.

protected void FetchingRates() 
{ 
    int count = 0; 
    List<RateLog> temp = new List<RateLog>(); 

    while (true) 
    { 
    try 
    { 
     if (m_RatesQueue.Count > 0) 
     {  
     lock (m_RatesQueue) 
     { 
      temp.AddRange(m_RatesQueue); 
      m_RatesQueue.Clear(); 
     } 

     foreach (RateLog item in temp) 
     { 
      m_ConnectionDataAccess.InsertRateLog(item); 
     } 

     temp.Clear(); 
     } 
     count++; 
     Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["RatesIntreval"].ToString())); 
    } 
    catch (Exception ex) 
    {     
    } 
    } 
} 

После temp.Clear() вы можете попробовать добавить GC.Collect();. Это НЕ должно быть постоянным решением, но может быть использовано для профилирования, чтобы увидеть, будут ли объекты в конечном итоге очищены. Если нет, то, возможно, все еще будет ссылка или событие.

+1

Это на самом деле должно * не * независимо от того, объявлен ли список тем внутри или вне цикла. –

+0

Правильно, его немного чище. * Rest * моего ответа касается того, что OP видит – SwDevMan81

0

Функция Clear() деконструирует список. Но как насчет экземпляров RateLog? Называется их деконструктор? Как насчет блокировки, возможно, это предотвратит удаление RateLog.

+0

, что я должен делать? Сделайте их Idisposable и зацикливайте их и вызовите dispose? – user437631

+0

Зависит от того, что в классе ... неуправляемых объектов? Объекты, которые должны быть удалены ?, и т. Д. – SwDevMan81

+0

№. очень простой класс с тремя строками \ date time \ int свойствами. – user437631

2
  1. Надеюсь, вы правильно разместите объекты ADO.NET. (Это просто хорошая практика.)
  2. Любые беспризорные ссылки сохранят ваши объекты RateLog от сбора GC.

Я рекомендую вам ознакомиться с кодом, начиная с создания объектов RateLog и принять во внимание все места, где хранится ссылка. Вот некоторые вещи, которые следует учитывать.

  1. Являются ли RateLog объектами подписки на любые мероприятия?
  2. Вы держите коллекцию RateLog объектов, сидящих где-то в статическом классе?

Вы также должны рассмотреть вопрос об инкапсулировании всей вашей защитной плитки для резьбы в классе.

public sealed class WorkQueue<T> 
{ 
    private readonly System.Collections.Generic.Queue<T> _queue = new System.Collections.Generic.Queue<T>(); 
    private readonly object _lock = new object(); 

    public void Put(T item) 
    { 
     lock (_lock) 
     { 
      _queue.Enqueue(item); 
     } 
    } 


    public bool TryGet(out T[] items) 
    { 
     if (_queue.Count > 0) 
     { 
      lock (_lock) 
      { 
       if (_queue.Count > 0) 
       { 
        items = _queue.ToArray(); 
        _queue.Clear(); 
        return true; 
       } 
      } 
     } 

     items = null; 
     return false; 
    } 
} 

Это позволит сделать ваш код намного яснее:

protected void FetchingRates() 
{ 
    int ratesInterval = int.Parse(ConfigurationManager.AppSettings["RatesIntreval"].ToString()); 
    int count = 0; 
    var queue = new WorkQueue<RateLog>(); 

    while (true) 
    { 
     try 
     { 
      var items = default(RateLog[]); 
      if (queue.TryGet(out items)) 
      { 
       foreach (var item in items) 
       { 
        m_ConnectionDataAccess.InsertRateLog(item); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      Logger.Log(ex);     
     } 

     Thread.Sleep(ratesInterval); 
     count++; 
    } 
} 
+0

Я использую один открытый SqlConnection. должен ли я распоряжаться объектами SqlComamnd? они сохраняют рефренс в моих журналах ставок? – user437631

+0

@ user437631: Да, вы должны. Общее правило: все, что реализует 'IDisposable', также требует, чтобы вы его распоряжались (или, по крайней мере, кто-то). Оберните свой 'SqlCommand' в' using' statement: 'using (SqlCommand dbc = GetStoredProcCommand (" InsertRateMonitoring ")) {/ * do stuff * /}' –

+0

@ user437631 - Как @ 0xA3 сказал, что вы должны распоряжаться объектами команды. Сама команда объектов не будет содержать ссылку на объект «RateLog», но вы можете хранить ссылку где-то еще в своем коде. – ChaosPandion

Смежные вопросы