c# - AvalonDock DocumentContent 未被垃圾收集

标签 c# wpf garbage-collection avalondock

我创建了一个使用 AvalonDock 框架的应用程序。一个关键部分是使用 AvalonDock.DocumentContent 派生编辑器编辑域模型实体的能力。我遇到了一个问题,发现我的编辑器在关闭并从 DockingManager.Documents 集合中删除后没有被垃圾回收。

经过一番无果而终的搜索后,我创建了一个可以按以下方式重新创建的小型测试应用程序:

  • 在 Visual Studio(我使用的是 2008)中,创建一个名为 AvalonDockLeak 的新 WPF 应用程序;
  • 添加对AvalonDock库的引用(我的版本是1.3.3571.0);
  • 添加一个名为 Document 的新用户控件;
  • 将 Document.xmal 更改为:

    <ad:DocumentContent x:Class="AvalonDockLeak.Document"
                        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock">
        <Grid>
            <TextBox />
        </Grid>
    </ad:DocumentContent>
    
  • 将 Document.xmal.cs 更改为:

    namespace AvalonDockLeak
    {
        using AvalonDock;
    
        public partial class Document : DocumentContent
        {
            public Document()
            {
                InitializeComponent();
            }
    
            ~Document()
            {
            }
        }
    }
    

    我添加的析构函数能够诊断问题,在打开 { 的方法上添加一个断点,并查看它是否被命中。它总是在关闭测试应用程序时执行,但不会更早。

  • 现在将 Window1.xaml 更改为:

    <Window x:Class="AvalonDockLeak.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
            Title="Memory Leak Test" Height="300" Width="300">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Button Name="NewButton" Click="NewButton_Click" Content="New" Height="26" Width="72" />
            <ad:DockingManager x:Name="DockManager" Grid.Row="1">
                <ad:DocumentPane />
            </ad:DockingManager>
        </Grid>
    </Window>
    
  • 将 Window1.xaml.cs 更改为:

    namespace AvalonDockLeak
    {
        using System.Windows;
    
        public partial class Window1 : Window
        {
            private int counter = 0;
    
            public Window1()
            {
                InitializeComponent();
            }
    
            private void NewButton_Click(object sender, RoutedEventArgs e)
            {
                string name = "Document" + (++this.counter).ToString();
                var document = new Document()
                {
                    Name = name,
                    Title = name,
                    IsFloatingAllowed = false
                };
    
                document.Show(this.DockManager);
                document.Activate();
            }
        }
    }
    

这个简单的应用程序也包含漏洞。这可以通过 ~Document() 上的断点观察到,打开 { not getting hit after closing a DocumentContent.

现在我想问的是,这是一个已知问题吗?有什么办法可以预防吗?如果对象只是在很长一段时间后才被垃圾收集,那么我该怎么做才能加快速度呢?顺便说一下,调用 GC.Collect() 没有帮助。

最佳答案

显然,您的 DocumentContent 的引用由某处的事件处理程序保存。你应该使用像 CLR-Profiler 这样的内存分析器从微软来确定原因。

您应该注意始终注销已注册的事件。否则你可能会发生内存泄漏。为此,您可以使用 -= 运算符。

关于c# - AvalonDock DocumentContent 未被垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6705343/

相关文章:

javascript - 是否可以在未连接互联网时继续使用 Web 应用程序?

c# - 如何在 MVC 中指定 textarea 的行列?

c# - WPF 数据网格 : Programmatically editing a cell

javascript - 如何动态更改表格列的内容

android - GC 是否保证释放未使用 Activity 的内存

java - 为什么从 java 9 PhantomReference java doc 开始,它专门用于 POST-mortem 清理操作,尽管它之前是 PRE-mortem

.net - 查找垃圾收集器上次在 .NET 中运行的时间

C# - 返回后在 catch block 中重新抛出异常

c# - 如何删除对象?

c# - Animation Completed 稍微到很快就会触发