AvalonDock DocumentContent 未被垃圾收集

发布于 2024-11-24 05:51:43 字数 2582 浏览 0 评论 0原文

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

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

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

    
        <网格>
            <文本框/>
        
    
    
  • 将 Document.xmal.cs 更改为:

    命名空间 AvalonDockLeak
    {
        使用 AvalonDock;
    
        公共部分类文档:DocumentContent
        {
            公共文件()
            {
                初始化组件();
            }
    
            〜文档()
            {
            }
        }
    }
    

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

  • 现在将 Window1.xaml 更改为:

    
        <网格>
            
                
                <行定义/>>
            
            <按钮名称=“NewButton”单击=“NewButton_Click”内容=“新建”高度=“26”宽度=“72”/>/>
            
                >
            
        
    
    
  • 将 Window1.xaml.cs 更改为:

    命名空间 AvalonDockLeak
    {
        使用系统.Windows;
    
        公共部分类 Window1 : 窗口
        {
            私有 int 计数器 = 0;
    
            公共窗口1()
            {
                初始化组件();
            }
    
            private void NewButton_Click(对象发送者, RoutedEventArgs e)
            {
                字符串名称 = "文档" + (++this.counter).ToString();
                var 文档 = 新文档()
                {
                    名字=名字,
                    标题=姓名,
                    是否允许浮动 = false
                };
    
                document.Show(this.DockManager);
                文档.Activate();
            }
        }
    }
    

这个简单的应用程序也包含泄漏。可以通过 ~Document() opening { 关闭 DocumentContent 后未命中的断点来观察。

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

I have created an application that makes use of the AvalonDock framework. A key part is the ability to edit domain-model entities using AvalonDock.DocumentContent derived editors. I hit upon a problem and discovered the my editors are not being garbage collected after they are closed and removed from the DockingManager.Documents collection.

After some fruitless searching I created a small test application that can be recreated in the following manner:

  • In Visual Studio (I'm using 2008), create a new WPF application called AvalonDockLeak;
  • Add a reference to the AvalonDock library (my version is 1.3.3571.0);
  • Add a new UserControl called Document;
  • Change Document.xmal to:

    <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>
    
  • Change Document.xmal.cs to:

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

    The destructor I have added to be able to diagnose the problem adding a breakpoint on the methods opening {, and seeing if it gets hit. It always does on closing the test application but not earlier.

  • Now change Window1.xaml to:

    <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>
    
  • Change Window1.xaml.cs to:

    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();
            }
        }
    }
    

This simple application also contains the leak. Which can be observed by the breakpoint on the ~Document() opening { not getting hit after closing a DocumentContent.

Now what I want to now is, is this a known problem and is there a way to prevent it? If the objects are only garbage collected after a long time then what can I do to expedite this? Calling GC.Collect() does not help by the way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

鸩远一方 2024-12-01 05:51:44

显然,您的 DocumentContent 的引用由事件处理程序保存在某处。您应该使用 Microsoft 的 CLR-Profiler 等内存分析器来确定原因。

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

obviously the references of your DocumentContent is kept by an eventhandler somewhere. you should use a memory-profiler like CLR-Profiler from microsoft to determine the cause.

you should take care that you always deregister an registered event. otherwise you can get a memory leak. for this you can use the -= operator.

守护在此方 2024-12-01 05:51:44

默认情况下,DocumentContent 将在关闭时隐藏,这意味着引用保持活动状态。

如果您希望 DocumentContent 关闭并随后进行处置,则需要在派生的 DocumentConcent 中指定几个属性或修改 AvalonDock 源。

        this.IsCloseable = true;
        this.HideOnClose = false;

现在,当关闭时,它将丢弃引用,而不是因为它只是被隐藏而保留它。

The DocumentContent will by default hide on close, which means the reference is kept alive.

If you want the DocumentContent to close and subsequently dispose you need to specify a couple of properties within a derived DocumentConcent or modify the AvalonDock source.

        this.IsCloseable = true;
        this.HideOnClose = false;

Now when closed, it will dispose of the reference versus hanging on to it as it was merely being hidden.

入怼 2024-12-01 05:51:44

我强烈建议您和任何使用 AvalonDock 1.3 的人升级到版本 2.0。
最新版本是 MVVM 友好的,并且不会遇到此问题(文档和锚定对象已正确垃圾收集)。
更多信息:avalondock.codeplex.com

谢谢

I strongly suggest you and anyone using AvalonDock 1.3 to upgrade to version 2.0.
Latest version is MVVM-friendly and doesn't suffer of this issue (Documents and Anchorables are correctly garbage collected).
More info: avalondock.codeplex.com

Thanks

纵情客 2024-12-01 05:51:44

我在这个方向上也遇到了问题。关闭选项卡会导致内存泄漏。我用探查器检查了它,结果发现 ActiveContent 仍然会保留引用,从而防止 GarbageCollector 启动。

我用于关闭选项卡的代码:

dc // DocumentContent, I want to close it
documentPane // DocumentPane, containing the dc

documentPane.Items.Remove(dc);

这完成了关闭选项卡的工作,但是了解如果我希望将 ActiveContent 设置为 null 并让 GC 完成它的工作,我需要

dc.Close();

在从 documentPane 中删除内容之前

调用。 注意:我使用 AvalonDock 1.2 版本,这可能在新版本中发生了变化。

I also had a problem in this direction. Closing tabs would cause memory leaks. I checked it with a profiler and it turned out that the ActiveContent would still keep a reference, preventing the GarbageCollector to kick in.

my code for closing the tab:

dc // DocumentContent, I want to close it
documentPane // DocumentPane, containing the dc

documentPane.Items.Remove(dc);

this did the job of closing the tab, but learned that I need to call

dc.Close();

before removing the content from the documentPane if I want ActiveContent to be set to null and let the GC do it's job.

Note: I use version 1.2 of AvalonDock, this may have changed in newer versions.

山田美奈子 2024-12-01 05:51:44

这看起来像是一个长期未解决的错误...:

http://avalondock.codeplex.com/workitem/9113

This looks like a long time outstanding bug...:

http://avalondock.codeplex.com/workitem/9113

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文