I'm unsure whether a child window is able to be garbage-collected in the following scenario.

  1. User control contains a "show popup" command
  2. The command creates a child window, and adds an anonymous listener for the "Closed" event.

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();
        });
    }
}

Since PopupCommand's delegate still ostensibly contains a reference the the local child variable, will each invocation of PopupCommand leak memory? Or will the garbage collector somehow recognize that it can dispose of child after it has been closed?


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

有帮助吗?

解决方案

The following test suggests that, no, the scenario does not result in a memory leak.

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();
        });
    }
}

The reason is suggested in the answer to the (Winforms) post linked to by Jwosty:

In your example, the publisher only exists within the scope of your private method, so both the dialog and the handler will be garbage collected at some point after the method returns.

In other words, the memory-leak concern is really the other way around -- the event publisher (the ChildWindow control) holds a reference to the subscriber (the DelegateCommand), but not the other way around. So, once the ChildWindow is closed, the garbage collector will free its memory.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top