Вопрос

Я задал этот вопрос раньше без реального ответа. Может кто-нибудь помочь? Я профилирую код ниже внутри синглтона и обнаружил, что множество ценных объектов (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;
        }
    }

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

Это было полезно?

Решение

Похоже, вы не отнимаете SqlCommand который висит на ратуче.

Другие советы

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

Функция CLEAR () деконструирует список. Но как насчет экземпляров Ratelog? Это их деконструктор называется? Как насчет блокировки, может быть, это предотвращает то, что рафиног из шкила удаляется.

Как насчет перемещения 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();. Отказ Это не должно быть постоянным решением, но можно использовать для вашего профилирования, чтобы посмотреть, в конечном итоге объекты очищаются. Если нет, то все еще может быть предложений или событие прилагается где-то.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top