使用带有加载/卸载事件的匿名委托时内存泄漏

时间:2013-10-09 06:27:22

标签: wpf memory-leaks user-controls

我有一个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....

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

我记得像加载,卸载这样的内部事件会被GC处理好吗?

当剂量匿名代表处置?

谢谢大家。

2 个答案:

答案 0 :(得分:0)

你说“应用程序会在运行几个小时后崩溃所以我添加了Unloaded事件” - 这是否意味着你经常在StackPanel内更改(添加和删除)UserControld?每当你创建一个新的UserControl时,你可以从MainWindow添加那些事件处理程序,对吗?

在这种情况下,你做得很好,并为Unloaded事件分配一个匿名委托,清理它是留下漂亮记忆足迹的正确方法。

答案 1 :(得分:0)

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

  • 使用和EventHandler方法代替匿名委托。
  • 在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....