2008-11-07 112 views
2

.Net中內存泄漏的常見原因之一是事件處理程序,它們永遠不會從其源對象中刪除。此WCF客戶端代碼是否會導致內存泄漏?

此WCF代碼是否會導致內存泄漏,或者lambda是否也會超出範圍,從而允許代理類和處理程序被GCed?

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

回答

2

這裏是我的測試 - 注意明確proxy設置爲null在lambda - 沒有它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

該對象將死亡...它將被清理。

不要忘了lamda沒有做任何特別的事情......這是一個編譯器技巧(所以只是假設它是一個正常的+ = SomeDelegate)。

此外,「關閉」方法(我不知道爲什麼他們沒有使它IDisposable)將清理所有剩下的東西。

1

不要忘記代理沒有正確實現IDisposable。如果發生錯誤,上面的代碼將不會清理連接,並且句柄將保留,直到父進程關閉。

0

其中lamdba定義將被捕獲,並將在上下文因此在編譯器創建的閉包類中「生存」(你可以在Reflector中看到它們) - 所以你的代理也是如此。使用弱事件處理程序或編寫代碼進行註銷。但在這種情況下,你不能使用lambda表達式。

相關問題