【问题标题】:Memory leak on Delegates with Callbacks带有回调的委托上的内存泄漏
【发布时间】:2012-07-30 06:44:54
【问题描述】:
 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 内存分析器,

清理对象的任何建议。

谢谢。

【问题讨论】:

  • 请参阅stackoverflow.com/questions/1774202/… 了解类似问题。不,只要委托和使用类共享相同的生命周期,就不存在内存泄漏。
  • 如果没有内存泄漏,不需要使用 EndInvoke() 吗?
  • 你的 SendCallback() 看起来有点递归......
  • 根据经验数据,无需使用 EndInvoke。

标签: c# memory-leaks delegates callback


【解决方案1】:

你一直在调用 mySend.BeginInvoke()。所以垃圾收集器总是在线程池线程的堆栈上看到对 mySend 对象的引用。因此不会收集它。当然,代码会一直运行下去。

在这种情况下不调用 EndInvoke() 是个坏主意,每次 BeginInvoke() 调用都会泄漏 10 分钟的资源。默认远程处理生命周期,远程处理是实现委托的 BeginInvoke() 方法的底层管道。

很难提出清理代码的建议,这样做没有多大意义。您不妨使用 while(true) {} 循环启动一个线程。那肯定会更有效率。

【讨论】:

  • 感谢您的回复。我在这里需要递归。如果我从 Dictionary 中添加/删除实例,我认为委托(使用 ThreadPool 线程)没有开销。在应用程序生命周期内添加了近 900 个对象。而 endinvoke(),我不想捕获异常(异常在 senddata 中被捕获(未发布(通过事件引发)))并且在调用回调时完成了 senddata。 endinvoke 还有其他原因吗?
  • 删除实例后,线程池线程自动死亡。从字典中删除对象后。我不再需要那个了。我已经尝试使代表无效。但保持不变。
  • 您的 cmets 与您的代码一样难以理解。我想我帮不了你。
猜你喜欢
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
相关资源
最近更新 更多