2012-07-30 15 views
4
public delegate void SendCallbackType(); 

    public class SenderBase 
    { 
     SenderBase() 
     { 
     mySend = new SendCallbackType(SendData); 
     mySend.BeginInvoke(SendCallback, null); 
     } 

    void SendData() 
    {    
     // process/sending data 
    } 

    void SendCallback(IAsyncResult ar) 
    {  
     **SendCallbackType worker = (SendCallbackType)((AsyncResult)ar).AsyncDelegate; 
     worker.EndInvoke(ar);** 

     //Above code is mandatory ? Working fine without them. 

     mySend.BeginInvoke(SendCallback, null); 

} 

// Test 
    Dictionary<SenderBase> SenderCollection = new Dictionary(); 
    SenderCollection.Add(new SenderBase()); 
    SenderCollection.Remove(0); 
// Add and remove seven times 

對象(SenderBase)不是垃圾回收。他們一直在向下一代轉移。帶回調代表的內存泄露

使用RedAnts內存分析器,

enter image description here

任何建議,以清理對象。

謝謝。

+1

有關類似問題,請參見http://stackoverflow.com/questions/1774202/not-calling-delegate-endinvoke-can-cause-memory-leak-a-myth。只要委託和使用類共享相同的生命週期,不會有內存泄漏。 – 2012-07-30 06:48:30

+0

如果沒有內存泄漏,不需要使用EndInvoke()? – 2012-07-30 06:57:34

+0

你的SendCallback()看起來有點遞歸... – 2012-07-30 07:00:50

回答

5

你一直在調用mySend.BeginInvoke()。所以垃圾收集器總是看到對線程池線程堆棧上的mySend對象的引用。因此不會收集它。當然代碼會一直運行。

在這種情況下不調用EndInvoke()是一個壞主意,它會爲每個BeginInvoke()調用泄漏資源10分鐘。默認的遠程處理生命期,遠程處理是實現委託的BeginInvoke()方法的底層管道。

很難想出清理代碼的建議,但這樣做沒什麼意義。你也可以用一段時間(true){}循環啓動一個線程。這肯定會更有效率。

+0

感謝您的回覆。我需要遞歸here.I認爲委託(使用ThreadPool線程)沒有開銷,如果我從Dictionary中添加/刪除實例。在應用程序生命週期中添加近900個對象。和endinvoke(),我不想要cath異常(異常被senddata(不張貼(通過事件引發))捕獲),並且senddata完成時,調用回調。任何其他原因endinvoke? – 2012-07-31 09:12:57

+0

我刪除實例後,線程池線程自動死了。從Dictionary中刪除對象後。我不再需要這個。我已經嘗試null代表。但保持不變。 – 2012-07-31 09:19:45

+1

你的評論和你的代碼一樣難以理解。我認爲我不能幫你。 – 2012-07-31 09:35:10