【发布时间】:2022-08-02 20:52:41
【问题描述】:
我有一个 Wpf 窗口,由于子 ComboBox 控件的固定项目数量相对较少而泄漏 - 所以我没有绑定它,只是直接添加 ComboBoxItem 项目。无论我尝试了什么,ComboBox 都会在新窗口关闭后保持它的活力。
我尝试了以下方法:
- 原文:在后面的代码中添加项目。
- 将项目直接移到 Xaml 中。
- 使用小型包装类将项目放入 ObservableCollection 中。
重现泄漏的最小步骤:
- 使用(尚未尝试在 .Net 5.0 或 6.0 中重现此内容)创建新的 Wpf 应用程序(.NET Framework [版本 4.7.2])项目。
- 向主窗口添加按钮
- 将 Window1 添加到解决方案中。
- 将以下基本 Xaml 和代码添加到 Window1。
- 为 MainWindow 上的按钮添加一个单击事件处理程序,并让它创建并显示 Window1。
- 编译并运行。
- 单击按钮,然后关闭 Window1。
- 在 Visual Studio 中,拍摄快照。打开快照并搜索“Window1”。
- 双击找到的\'Window1\'实例。
- 请注意,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 的内存泄漏。
有没有更好的方法来处理这个?