Будет ли этот код на стороне клиента WCF вызывать утечку памяти? - PullRequest
2 голосов
/ 07 ноября 2008

Одной из частых причин утечек памяти в .Net являются обработчики событий, которые никогда не удаляются из их исходных объектов.

Приведет ли этот код WCF к утечке памяти или лямбда также выйдет из области видимости, что позволит GCed прокси-классу и обработчику?

void AMethod()
{
    WCFClient proxy;
    proxy = new WCFClient();
    proxy.RemoteOperationCompleted += (sender, e) => proxy.Close();
    proxy.Open();
    proxy.RemoteOperationAsync();
}

Ответы [ 4 ]

2 голосов
/ 07 ноября 2008

Вот мой тест - обратите внимание на явное proxy, установленное на null в лямбда-выражении - без него WeakReference живет и, следовательно, возможна утечка:

public class Proxy
{
    private bool _isOpen;

    public event EventHandler Complete;

    public void Close() 
    {
        _isOpen = false;
    }

    public void Open() 
    { 
        _isOpen = true; 
    }

    public void RemoteOperationAsync()
    {
        if (!_isOpen)
            throw new ApplicationException();
        Thread.Sleep(1000);
        if (Complete != null)
            Complete(this, EventArgs.Empty);
    }
}

public static class Program
{
    public static void Main()
    {
        WeakReference wr = null;

        {
            var proxy = new Proxy();
            proxy.Complete += (sender, e) =>
                {
                    proxy.Close();
                    wr = new WeakReference(proxy);
                    proxy = null;
                };
            proxy.Open();
            proxy.RemoteOperationAsync();
        }

        GC.Collect(GC.GetGeneration(wr));
        GC.WaitForPendingFinalizers();

        Console.WriteLine("[LAMBDA] Is WeakReference alive? " + wr.IsAlive);
    }
}
1 голос
/ 07 ноября 2008

Не забывайте, что прокси не правильно реализуют IDisposable. Если произойдет ошибка, приведенный выше код не очистит соединение, и дескриптор останется до закрытия родительского процесса.

0 голосов
/ 20 октября 2011

Контекст, в котором определена lamdba, будет захвачен и, следовательно, «выживет» в созданном компилятором классе замыкания (вы можете увидеть их с помощью Reflector) - так что ваш прокси тоже. Используйте слабый обработчик событий или напишите код для отмены регистрации. Но в этом случае вы не можете использовать лямбда-выражение.

0 голосов
/ 07 ноября 2008

Этот объект умрет ... он будет очищен.

Не забывайте, что lamda не делает ничего особенного ... это трюк с компилятором (поэтому предположим, что это обычный + = SomeDelegate).

Кроме того, метод «Закрыть» (я не знаю, почему они не сделали его IDisposable) очистит все остальное, что осталось открытым.

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