Así que estoy usando WPF 3.5 con el método MVVM + DataTemplate para cargar 2 vistas en la GUI. ¡He observado mientras que el perfil de la memoria que los elementos generados como parte del contenedor de artículos de los controles de artículos se anclan en la memoria y no se acumulan GC incluso después de que se descargue la vista!Instancias anotadas para GC - No detectable desde mi código administrado
Acabo de ejecutar pruebas y descubrí que es reproducible incluso para el código más simple ... Ustedes pueden comprobarlo por sí mismos.
XAML:
<Window x:Class="ContentControlVMTest.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentControlVMTest"
Title="Window2" Height="300" Width="300">
<DockPanel LastChildFill="True">
<CheckBox Click="CheckBox_Click" Content="Test1?"
DockPanel.Dock="Top" Margin="5"/>
<ContentControl x:Name="contentControl">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:Test3}">
<TextBlock Text="{Binding C}" Margin="5"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Test1}">
<DockPanel LastChildFill="True" Margin="5">
<TextBlock Text="{Binding A}"
DockPanel.Dock="Top"
Margin="5"/>
<ListBox ItemsSource="{Binding Bs}"
DisplayMemberPath="B"
Margin="5"/>
</DockPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</Window>
código subyacente:
public class Test3
{
public string C { get; set; }
}
public class Test2
{
public string B { get; set; }
}
public class Test1
{
public string A { get; set; }
private List<Test2> _Bs;
public List<Test2> Bs
{
get
{
return _Bs;
}
set
{
_Bs = value;
}
}
}
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
this.KeyDown += Window_KeyDown;
}
private void Window_KeyDown
(object sender, System.Windows.Input.KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl))
if (Keyboard.IsKeyDown(Key.LeftShift))
if (Keyboard.IsKeyDown(Key.LeftAlt))
if (Keyboard.IsKeyDown(Key.G))
{
GC.Collect(2, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(2, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(3, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(3, GCCollectionMode.Forced);
}
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
if (((CheckBox)sender).IsChecked.GetValueOrDefault(false))
{
var x = new Test1() { A = "Test1 A" };
x.Bs = new List<Test2>();
for (int i = 1; i < 10000; i++)
{
x.Bs.Add(new Test2() { B = "Test1 B " + i });
}
contentControl.Content = x;
}
else
{
contentControl.Content = new Test3() { C = "Test3 C" };
}
}
}
llevo a cabo GC obligado por desplazamiento a la izquierda + Alt + Ctrl + G. Todos los artículos para la vista Test1
o Test3
y Ver modelo se muere después de que se descargan correctamente. Entonces eso es lo esperado.
Pero la colección generada en el modelo Test1
(que tiene objetos Test2
), permanece anclada en la memoria. ¡Y indica que la matriz es la utilizada por el contenedor de elementos del listbox porque muestra la cantidad de elementos desvirtualizados del listbox! ¡Esta matriz anclada cambia su tamaño cuando minimizamos o restauramos la vista en el modo de vista Test1
! Una vez fueron 16 ítems y la próxima vez fue 69 ítems cuando se perfilaron.
Esto significa WPF realiza la fijación de elementos generados en artículos controles! ¿Alguien puede explicar esto? ¿Esto tiene algún inconveniente significativo?
Thx mucho.
Tal vez un 'CollectionView' creado para la colección está dando vueltas. – user7116
thx para la respuesta. ¡Sí! Es la colección de elementos del contenedor de artículos. Pero ¿por qué sería eso dando vueltas? La vista se ha ido. ListBox se ha ido. ¿Por qué WPF fijaría colecciones en la memeoría? –
Podría publicar la raíz para la instancia fijada por favor. –