我创建了一个应用程序,使用了AvalonDock框架。其中一个关键部分是使用AvalonDock.DocumentContent
派生的编辑器来编辑领域模型实体。我遇到了一个问题,发现我的编辑器在关闭并从DockingManager.Documents
集合中删除后没有被垃圾回收。
经过一些无果的搜索后,我创建了一个小型测试应用程序,可以按照以下方式重新创建:
- 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(); } } }
这个简单的应用程序也存在泄露。当关闭 DocumentContent
后,可以通过断点观察到打开 ~Document()
的大括号未被命中。
现在我想知道的是,这是一个已知问题吗?是否有方法来防止它?如果对象只有在很长时间后才被垃圾回收,那么我该怎么办才能加速这个过程?顺便说一下,调用 GC.Collect() 也没有帮助。
document.Show(this.DockManager);
是做什么的。我猜这个文档以某种方式向管理器注册自己,并且没有被正确注销。在DockManager上是否有一种方法可以删除文档? - ChrisWuemanager.Documents.Add(this);
。文档关闭后,它也不再存在于manager.Documents
集合中。 - Wietze