【问题标题】:Wpf Unbound ComboBox leakWpf Unbound ComboBox 泄漏
【发布时间】:2022-08-02 20:52:41
【问题描述】:

我有一个 Wpf 窗口,由于子 ComboBox 控件的固定项目数量相对较少而泄漏 - 所以我没有绑定它,只是直接添加 ComboBoxItem 项目。无论我尝试了什么,ComboBox 都会在新窗口关闭后保持它的活力。

我尝试了以下方法:

  1. 原文:在后面的代码中添加项目。
  2. 将项目直接移到 Xaml 中。
  3. 使用小型包装类将项目放入 ObservableCollection 中。

    重现泄漏的最小步骤:

    1. 使用(尚未尝试在 .Net 5.0 或 6.0 中重现此内容)创建新的 Wpf 应用程序(.NET Framework [版本 4.7.2])项目。
    2. 向主窗口添加按钮
    3. 将 Window1 添加到解决方案中。
    4. 将以下基本 Xaml 和代码添加到 Window1。
    5. 为 MainWindow 上的按钮添加一个单击事件处理程序,并让它创建并显示 Window1。
    6. 编译并运行。
    7. 单击按钮,然后关闭 Window1。
    8. 在 Visual Studio 中,拍摄快照。打开快照并搜索“Window1”。
    9. 双击找到的\'Window1\'实例。
    10. 请注意,Window1 由直接引用 ComboBox 或 ComboBoxItem 的事件处理程序/事件参数保持活动状态。

      根据我尝试过的方法,内存泄漏的痕迹会发生一些变化,但它总是某种我无权访问的内部事件处理程序/事件参数,它对 ComboBox 或 ComboBoxItem 有硬引用,它是保持 Window1 活着。

      xml:

      <Window x:Class=\"WpfComboBoxLeak.Window1\"
              xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
              xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
              xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"
              xmlns:local=\"clr-namespace:WpfComboBoxLeak\"
              xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"
              Title=\"Window1\"
              Width=\"800\"
              Height=\"450\"
              mc:Ignorable=\"d\">
          <Grid>
              <ComboBox x:Name=\"cbo\" />
          </Grid>
      </Window>
      

      后面的代码:

      public partial class Window1 : Window
      {
          public Window1()
          {
              InitializeComponent();
      
              AddItem(1, \"One\");
              AddItem(2, \"Two\");
              AddItem(3, \"Three\");
          }
      
          private void AddItem(object value, string display)
          {
              cbo.Items.Add(new ComboBoxItem()
              {
                  Content = display,
                  Tag = value,
              });
          }
      }
      

      这是一个示例泄漏跟踪:

      WpfComboBoxLeak.Window1    <0x2C6B30C>
          ComboBoxItem    <0x2C74718> 
              ArrayList    <0x2C74DA8> 
                  ItemCollection    <0x2C72D80> 
                      EventHandler<NotifyCollectionChangedEventArgs>    <0x2C85E84> [Dependent Handle, ItemCollection <0x2C72D80>]
                      EventHandler<EventArgs>    <0x2C85A40> [Dependent Handle, ItemCollection <0x2C72D80>]
                      EventHandler<CurrentChangingEventArgs>    <0x2C85840> [Dependent Handle, ItemCollection <0x2C72D80>]
                      EventHandler<NotifyCollectionChangedEventArgs>    <0x2C8566C> [Dependent Handle, ItemCollection <0x2C72D80>]
                      ItemCollection    <0x2C72D80> [Cycle Detected]
                      EventHandler<PropertyChangedEventArgs>    <0x2C85C40> [Dependent Handle, ItemCollection <0x2C72D80>]
                      ItemContainerGenerator    <0x2C7300C> 
                      ComboBox    <0x2C710E8>    
      

      编辑:我找到了一个解决方案——有点——但我不太喜欢它。如果我向 Window1 添加一个 Window Closing 事件处理程序,并在其中从它的父容器中删除 ComboBox,泄漏就会消失。

      对我来说很奇怪的是,我必须处理 Window Closing 事件并从父容器中删除给定 Window 上的任何组合框,否则我会得到该 Window 的内存泄漏。

      有没有更好的方法来处理这个?

    标签: c# wpf


    【解决方案1】:

    莫因, 我有同样的问题。 我认为 Wpf 中的某些内容发生了变化。 我在很久以前创建的窗口中发现了内存泄漏并对其进行了测试,以便当时没有内存泄漏。 我开始测试它的来源(我一个接一个地删除控制,直到泄漏消失)。 要重现它,只需向窗口添加一个 ComboBox 就足够了(没有事件,只是一个名称而已)。 如果我删除 ComboBox,泄漏就消失了。 有没有更好的方法作为线程创建者来消除泄漏?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2010-12-05
      • 2011-03-19
      相关资源
      最近更新 更多