我不确定在以下场景中是否可以对子窗口进行垃圾收集。
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
答案 0 :(得分: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
关闭,垃圾收集器将释放其内存。