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.
document.Show(this.DockManager);
does. I guess the document registers itself in some way with the manager and it's not being unregistered properly. Is there a method on the DockManager to remove documents? – Massetermanager.Documents.Add(this);
. After the document is closed it is also no longer present in themanager.Documents
collection. – Cherilyncherilynn