2

.Netでのメモリリークのよくある原因の1つは、ソースオブジェクトから削除されないイベントハンドラーです。

このWCFコードはメモリリークを引き起こしますか、それともラムダもスコープ外になり、プロキシクラスとハンドラーの両方をGCできるようになりますか?

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

4 に答える 4

2

これが私のテストです-ラムダで明示的にproxy設定されていることに注意してください-それなしでは生きているので、リークが発生する可能性があります:nullWeakReference

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);
    }
}
于 2008-11-07T05:05:26.440 に答える
1

プロキシがIDisposableを正しく実装していないことを忘れないでください。エラーが発生した場合、上記のコードは接続をクリーンアップせず、親プロセスが閉じられるまでハンドルは残ります。

于 2008-11-07T04:39:09.660 に答える
0

lamdba が定義されているコンテキストがキャプチャされるため、コンパイラで作成されたクロージャ クラスで「存続」します (Reflector でそれらを確認できます) - したがって、プロキシも同様です。弱いイベント ハンドラーを使用するか、登録解除用のコードを記述します。ただし、その場合、ラムダ式は使用できません。

于 2011-10-20T18:20:16.847 に答える
-1

そのオブジェクトは死にます...クリーンアップされます。

ラムダが特別なことをしていないことを忘れないでください...これはコンパイラのトリックです(通常の += SomeDelegate であると仮定してください)。

また、「Close」メソッド (IDisposable にしなかった理由はわかりません) は、開いたままになっている他のすべてのものをクリーンアップします。

于 2008-11-07T04:20:11.727 に答える