Утечка памяти при использовании AppDomain.CurrentDomain.AssemblyResolve - PullRequest
1 голос
/ 23 февраля 2012

Следующий код имеет утечку памяти.

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 10; i++)
        {
            AssemblyResolveMemoryTest assemblyResolveMemoryTest = new AssemblyResolveMemoryTest();
        }
    }
}

class AssemblyResolveMemoryTest 
{
    private byte[] _allocateMemory;

    public AssemblyResolveMemoryTest()
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        //memory is not released anymore
        _allocateMemory = new byte[300000000]; 
    }
    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        return null;
    }
}

Кажется, событие AssemblyResolve вызывает утечку памяти.

В чем причина?Нужно ли явно удалять обработчик событий в этом случае?Если да, где находится правильное место для удаления этого обработчика событий?Реализовать IDisposable или использовать Try / Наконец?

1 Ответ

3 голосов
/ 23 февраля 2012

Да, событие приведет к утечке памяти. Это потому, что AppDomain.CurrentDomain.AssemblyResolve является статическим, поэтому его жизнь не заканчивается до завершения программы. Поэтому ему придется хранить ссылку на все зарегистрированные обработчики событий (+ =), чтобы они оставались в памяти при возникновении события, которое приведет к вызову обработчиков.

Я бы посоветовал вам реализовать IDisposable в классе AssemblyResolveMemoryTest и получить его для - = событие.

Затем в цикле for добавьте оператор using, который вызовет dispose.

    for (int i = 0; i < 10; i++)
    {
        using( AssemblyResolveMemoryTest assemblyResolveMemoryTest = new AssemblyResolveMemoryTest() )
        {
        }
    }

Вы можете сохранить экземпляры assemblyResolveMemoryTest в списке и написать второй цикл, который обходит их, вызывая Dispose до того, как ваша программа существует. Хотя в этом нет особого смысла, потому что, когда ваша программа существует, все будет утилизировано и «утечка памяти» будет освобождена.

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

Полагаю, буфер - это не то, что есть в реальной программе, и вы просто используете его для демонстрации проблемы. Возможно, если у вас есть память, на которую ссылается ваш реальный эквивалент AssemblyResolveMemoryTest в производственном коде, вы можете попытаться реструктурировать свою программу так, чтобы обработчик событий для AssemblyResolve не был частью объекта, который содержит другую память, которая не имеет отношения к обработка события.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...