したがって、MVVM + DataTemplateメソッドでWPF 3.5を使用してGUIで2つのビューをロードしています。アイテムコントロールのアイテムコンテナの一部として生成されたアイテムがメモリに固定され、ビューがアンロードされた後でもGCedが取得されないというメモリプロファイリングを観察しました!GCの固定インスタンス - マネージコードからトレースできません
私はちょうどテストを実行し、それがコードの最も単純なものであっても再現可能であることがわかりました。皆さんは自分で確認できます。
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>
コード:
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" };
}
}
}
私は左Shift + Altキー+ Ctrlキー+ GによってTest1
またはTest3
ビューのためにすべてのアイテムを強制的にGCを実行し、ビューモデルが正しくアンロードされた後に死んでしまいます。だからそれは期待通りです。
ただし、Test1
モデル(オブジェクトがTest2
)に生成されたコレクションは、メモリに固定されたままです。リストボックスから非仮想化項目の数が表示されるため、配列はリストボックスの項目コンテナで使用される配列であることを示します。このピン配列は、ビューモードをTest1
ビューで最小化または復元するとサイズが変わります! 1回は16項目、次回はプロファイル時に69項目でした。
これは、WPFは、項目のコントロールで生成されたアイテムのピン止めを行い、意味!誰もこれを説明できますか?これには重大な欠点がありますか?
Thxたくさん。
おそらく 'CollectionView'がうろついているコレクションのために作成しました。応答のための – user7116
thx。はい!アイテムコンテナからのアイテムコレクションです。しかし、なぜそれが周りにぶら下がっているだろうか?見えなくなったListBoxはなくなっています。なぜWPFは連邦議会でコレクションをピン止めするのだろうか? –
固定インスタンスのルートを投稿してください。 –