我正在动态地在WPF应用程序中加载和卸载内容,以启用可扩展的框架来向用户呈现大量的异构数据。
有时,当丢弃动态加载的内容时,会导致内存泄漏。例如,在名为Workspace的框架中显示的SyncFusion GridControl如下:
ControlTemplate template = (ControlTemplate)Workspace.FindResource("SfGridTemplate");
DependencyObject root = template.LoadContent();
Workspace.Content = root;
GridControl dataItemsGrid = (GridControl)LogicalTreeHelper.FindLogicalNode(root, "SfGridControl");
....
在Xaml中定义资源SfGridTemplate的地方:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GCTest"
xmlns:sf="http://schemas.syncfusion.com/wpf">
<ControlTemplate x:Key="SfGridTemplate">
<Grid>
<sf:GridControl Name="SfGridControl" ...>
<sf:GridControl.Resources>
....
</sf:GridControl.Resources>
</sf:GridControl>
</Grid>
</ControlTemplate>
</ResourceDictionary>
加载后,我打印出窗口的逻辑树(但请参见下面的PS):
GCTest.MainWindow
System.Windows.Controls.Grid
....
System.Windows.Controls.Frame Workspace
System.Windows.Controls.Grid
Syncfusion.Windows.Controls.Grid.GridControl
我现在通过Workspace.Grid.Children.RemoveAt(0)从框架中删除GridControl并再次打印出逻辑树:
GCTest.MainWindow
System.Windows.Controls.Grid
....
System.Windows.Controls.Frame Workspace
System.Windows.Controls.Grid
显然,GridControl对象已被删除。但是,Visual Studio中的堆诊断仍然显示:
Syncfusion.Windows.Controls.Grid.GridControl 1 62,452 135,664
带有拜占庭式的“根目录路径”列表,其中涉及Hashtable,ListDictionary,DictionaryNode,HybridDictionary ...对象,这些我无法理解。强制使用GC.Collect或GridCOntrol.Dispose对此行为没有影响。
最终结果是,当应用程序加载和卸载某些UI元素时,它似乎会泄漏内存。如上所述,SyncFusion GridControl会导致泄漏,但例如SyncFusion SfChart不会。
寻找类似问题后,我已经消除了内存泄漏的可能原因:事件处理程序,计时器,数据绑定(上述测试应用程序中没有使用这些处理程序)。
(1)为什么GridControl对象显然是由某个根对象持有的?
(2)如何删除该引用,以便可以回收内存?
可能有一个相关的奇数:LogicalTreeHelper.GetChildren(Workspace)(即我将内容加载到其中的Frame的子代)始终返回一个空列表,我必须执行Workspace.Content才能在列表中查看DataGrid控件。逻辑树。