2012-12-21 32 views
2

我不确定在以下情况下是否可以对子窗口进行垃圾回收。匿名委托事件侦听器是否会阻止垃圾收集?

  1. 用户控件包含一个“秀弹出”命令
  2. 的命令创建一个子窗口,并增加了一个匿名侦听器“关闭”事件。

public partial class MainPage : UserControl 
{ 
    public ICommand PopupCommand { get; private set; } 

    public MainPage() 
    { 
     InitializeComponent(); 

     PopupCommand = new DelegateCommand(arg => 
     { 
      var child = new ChildWindow(); 
      child.Closed += (sender, args) => 
      { 
       MessageBox.Show("You closed the window!"); 
      }; 
      child.Show(); 
     }); 
    } 
} 

PopupCommand以来的代表仍表面上包含一个参考的本地child变量,将的PopupCommand泄漏存储器每次调用?或者垃圾收集器会以某种方式认识到它可以在关闭后处置child


相关:detaching anonymous listeners from events in C# and garbage collection

+1

我认为这是重复的:http://stackoverflow.com/questions/9591195/detaching-anonymous-listeners-from-events-in-c-sharp-and-garbage-collection – Jwosty

+0

你需要有一个 - 你不会..? http://stackoverflow.com/questions/4303922/removing-anonymous-event-handler – MethodMan

+0

@DJKRAZE它看起来像你实际上不需要' - ='。这对我来说也是令人惊讶的。 – McGarnagle

回答

1

下面的测试表明,没有,该方案不会导致内存泄漏。

public partial class LeakTest : UserControl 
{ 
    public ICommand PopupCommand { get; private set; } 

    public LeakTest() 
    { 
     InitializeComponent(); 

     PopupCommand = new DelegateCommand(arg => 
     { 
      var child = new ChildWindow(); 
      child.Closed += (sender, args) => 
      { 
       System.Diagnostics.Debug.WriteLine("Closed window"); 
      }; 

      // when the window has loaded, close it and re-trigger the command 
      child.Loaded += (sender, args) => 
      { 
       child.Close(); 
       PopupCommand.Execute(null); 
      }; 
      child.Show(); 
     }); 
    } 
} 

究其原因,建议在答案(Winforms) post linked to by Jwosty

在您的例子,出版商只有你的私有方法的范围内的存在,所以不管是对话和处理将是垃圾在方法返回后的某个时间点收集。

换句话说,内存泄漏问题是真的倒过来 - 事​​件发布者(在ChildWindow控制)持有的用户(在DelegateCommand)的参考,而不是周围的其他方式。所以,一旦ChildWindow关闭,垃圾收集器将释放其内存。