此WCF客户端代码是否会导致内存泄漏?

时间:2008-11-07 03:52:19

标签: c# .net wcf lambda

.Net中内存泄漏的常见原因之一是事件处理程序,它们永远不会从源对象中删除。

此WCF代码是否会导致内存泄漏,或者lambda是否也会超出范围,允许代理类和处理程序进行GC操作?

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

4 个答案:

答案 0 :(得分:2)

这是我的测试 - 请注意lambda中显式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 :(得分:1)

不要忘记代理服务器没有正确实现IDisposable。如果发生错误,上面的代码将不会清除连接,并且句柄将保持不变,直到父进程关闭。

答案 2 :(得分:0)

将捕获定义lamdba的上下文,因此将在编译器创建的闭包类中“生存”(您可以使用Reflector查看它们) - 所以您的代理也是如此。使用弱事件处理程序或编写代码进行取消注册。但在这种情况下,你不能使用lambda表达式。

答案 3 :(得分:-1)

那个物体会死......它会被清理干净。

不要忘记lamda没有做任何特别的事情......这是一个编译技巧(所以假设它是正常的+ = SomeDelegate)。

此外,“关闭”方法(我不知道为什么他们没有使它成为IDisposable)将清理剩下的所有其他东西。