我创建了一个使用AvalonDock框架的应用程序。关键部分是使用AvalonDock.DocumentContent
派生编辑器编辑域模型实体的能力。我遇到了一个问题,发现我的编辑在关闭并从DockingManager.Documents
集合中删除后没有被垃圾收集。
经过一些无效的搜索后,我创建了一个小型测试应用程序,可以通过以下方式重新创建:
AvalonDockLeak
的新WPF应用程序; 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()
开头的断点可以观察到{关闭DocumentContent
后没有被击中。
现在我想要的是,这是一个已知的问题,是否有办法防止它?如果对象在很长一段时间后才被垃圾收集,那么我该怎样做才能加速呢?调用GC.Collect()并没有帮助。
答案 0 :(得分:4)
显然,DocumentContent的引用由某个事件处理程序保存。你应该使用来自microsoft的CLR-Profiler这样的内存分析器来确定原因。
您应该注意始终注销已注册的活动。否则你可能会发生内存泄漏。为此,您可以使用 - =运算符。
答案 1 :(得分:3)
DocumentContent
默认隐藏在关闭状态,这意味着引用保持活动状态。
如果您希望DocumentContent
关闭并随后处置,则需要在派生DocumentConcent
内指定一些属性或修改AvalonDock
来源。
this.IsCloseable = true;
this.HideOnClose = false;
现在当它关闭时,它会处理引用而不是挂在它上面,因为它只是被隐藏了。
答案 2 :(得分:2)
我也遇到了这方面的问题。关闭选项卡会导致内存泄漏。我用一个分析器检查了它,结果发现 ActiveContent 仍会保留一个引用,阻止GarbageCollector启动。
关闭标签的代码:
dc // DocumentContent, I want to close it
documentPane // DocumentPane, containing the dc
documentPane.Items.Remove(dc);
这完成了关闭标签的工作,但了解到我需要调用
dc.Close();
在从documentPane中删除内容之前,如果我想将 ActiveContent 设置为 null 并让GC执行此操作。
注意:我使用的是AvalonDock的1.2版本,这可能在较新的版本中有所改变。
答案 3 :(得分:1)
这看起来像是一个长期存在的错误......:
答案 4 :(得分:1)
我强烈建议您和使用AvalonDock 1.3的任何人升级到2.0版。 最新版本是MVVM友好的,并没有遇到这个问题(Documents and Anchorables正确垃圾收集)。 更多信息:avalondock.codeplex.com
由于