утечка памяти .net 4? - PullRequest
       16

утечка памяти .net 4?

2 голосов
/ 28 марта 2012

Я использую MemoryCache с зависимостями Sql. Я заметил, что при использовании MemoryCache.Set () происходит утечка памяти, если элемент перезаписывается в коллекции. Рассмотрим следующий сценарий:

  1. Элемент с ключом = A вставляется в кеш с зависимостью от Table1
  2. Новый элемент с тем же ключом = a повторно вставляется с помощью .Set () с зависимостью от Table2
  3. Таблица 2 изменилась в базе данных.

-> Ключ элемента = a действительно был удален из кэша, но его память все еще используется в MemoryCache. Память освобождается только при изменении данных для Таблицы 1 в базе данных.

Воспроизвести код:

public partial class Form1 : Form
{
    const string cs = @"Data Source=.\sqlexpress;Initial Catalog=TestDB;";
    public Form1()
    {
        SqlDependency.Start(cs);
        InitializeComponent();
    }

    MemoryCache memCache = new MemoryCache("test1", new NameValueCollection { 
        { "pollingInterval", "00:00:03"}});

    private void button2_Click(object sender, EventArgs e)
    {
        var dep1 = GetDep("SELECT ID FROM dbo.Table1");
        var dep2 = GetDep("SELECT ID FROM dbo.Table2");

        var policy = new CacheItemPolicy();
        policy.SlidingExpiration = new TimeSpan(2, 0, 0);
        policy.ChangeMonitors.Add(new SqlChangeMonitor(dep1));

        memCache.Set("a", GetSB(), policy);

        var policy2 = new CacheItemPolicy();
        policy2.SlidingExpiration = new TimeSpan(2, 0, 0);
        policy2.ChangeMonitors.Add(new SqlChangeMonitor(dep2));

        memCache.Set("a", GetSB(), policy2);
    }

    private object GetSB()
    {
        StringBuilder sb = new StringBuilder(100000000);
        for (var i = 0; i < sb.Capacity; i++)
        {
            sb.Append("1");
        }
        return sb.ToString();
    }

    private static SqlDependency GetDep(string sql)
    {
        SqlConnection con = new SqlConnection(cs);
        var cmd = new SqlCommand(sql, con);
        SqlDependency dep = new SqlDependency(cmd);
        con.Open();
        cmd.ExecuteNonQuery();
        con.Close();
        return dep;
    }

    private void button3_Click(object sender, EventArgs e)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        MessageBox.Show("Total Memory Usage = " + GC.GetTotalMemory(true).ToString());
    }

    private void button1_Click(object sender, EventArgs e)
    {
        bool exists = memCache.Get("a") != null;
        MessageBox.Show("Value exits -> " + exists);
    }
}

Чтобы использовать код, нажмите кнопку Button2 для инициализации, затем измените данные таблицы 2 в базе данных. используйте Button3 для просмотра доступной памяти.

1 Ответ

0 голосов
/ 06 июля 2018

Вероятно, отвечу на это через долгое время.

открытый переопределенный объект Remove (строковый ключ, строка regionName = null);

Перед вставкой / заменой кэшированных данных следует удалить старый ключ.

...