将匿名委托与加载/卸载事件一起使用时出现内存泄漏



我有一个WPF MainWindow,可以在StackPanel中更改(导航)UserControl:

// on code behind of MainWindow     
RootStackPanel.Children.Clear();
                UserControl1 uc1= new UserControl1();
                uc1.CustomizedEvent1+= EventHandler1;
                uc1.CustomizedEvent2+= EventHandler2;
                uc1.Loaded += (s, e1) =>
                 {
                        // Do something
                 };
                // Unsubscribe external event to prevent memory leak
                uc1.Unloaded += (s, e1) =>
                    {
                        uc1.CustomizedEvent1 -= EventHandler1;
                        uc1.CustomizedEvent2 -= EventHandler2;
                    };
RootStackPanel.Children.Add(uc1);
// same for UserControl 2,3,4....

应用程序在运行几个小时后会崩溃,所以我添加了带有匿名委托的卸载事件处理程序,以通过取消订阅用户控件的所有事件来防止内存泄漏。使用匿名委托卸载会导致内存泄漏吗?如果是,如何在不调用卸载的情况下取消订阅用户控件的所有事件?

我记得像加载、卸载这样的内部事件将由 GC 处理,对吗?

什么时候剂量匿名代表处置?

谢谢大家。

你说"应用程序在运行几个小时后会崩溃,所以我添加了卸载事件" - 这是否意味着你经常在该StackPanel中更改(添加和删除)UserControld?此外,每次创建新的用户控件时,您都会从 MainWindow 添加这些事件处理程序,对吗?

在这种情况下,您做得很好,将匿名委托分配给清理的卸载事件是留下漂亮内存占用的正确方法。

我找到了解决此问题的简单解决方案:

  • 使用 and EventHandler 方法,而不是匿名委托。
  • 在事件处理程序方法中调用 Unsubsribe。

    .....
    // on code behind of MainWindow     
    RootStackPanel.Children.Clear();
            UserControl1 uc1= new UserControl1();
            uc1.CustomizedEvent1+= EventHandler1;
            uc1.CustomizedEvent2+= EventHandler2;               
            // Unsubscribe external event to prevent memory leak
            //uc1.Unloaded += (s, e1) =>
             //   {
             //       uc1.CustomizedEvent1 -= EventHandler1;
             //       uc1.CustomizedEvent2 -= EventHandler2;
             //   };
    RoutedEventHandler unloadedHandler = null;
    unloadedHandler = delegate(object s, RoutedEventArgs sev)
        {
     uc1.CustomizedEvent1 -= EventHandler1;
             uc1.CustomizedEvent2 -= EventHandler2;
    uc1.Unloaded -= unloadedHandler;
    };
        uc1.Unloaded += unloadedHandler;
    RootStackPanel.Children.Add(uc1);
    // same for UserControl 2,3,4....
    

最新更新