Vì vậy, tôi đang sử dụng WPF 3.5 với phương pháp MVVM + DataTemplate để tải 2 chế độ xem trên GUI. Tôi đã quan sát thấy trong khi bộ nhớ định hình rằng các mục được tạo ra như một phần của các thùng chứa các mục điều khiển được gắn vào bộ nhớ và không nhận được GC ngay cả sau khi xem được dỡ bỏ!Trường hợp được ghim cho GC - Không thể theo dõi từ mã được quản lý của tôi
Tôi vừa chạy thử nghiệm và phát hiện ra nó có thể tái sản xuất ngay cả đối với mã đơn giản nhất ... Các bạn có thể tự kiểm tra.
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>
Mã Đằng sau:
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" };
}
}
}
tôi thực hiện buộc GC bằng phím Shift trái + Alt + Ctrl + G. Tất cả các mục cho xem Test1
hoặc Test3
và Xem mẫu bị chết sau khi chúng được tải xuống một cách chính xác. Vì vậy, đó là như mong đợi.
Nhưng bộ sưu tập được tạo trong mô hình Test1
(có Test2
đối tượng), vẫn được ghim vào bộ nhớ. Và nó chỉ ra rằng mảng là mảng được sử dụng bởi các thùng chứa các mục của hộp danh sách bởi vì nó cho thấy số lượng các mục bị ảo hóa khỏi hộp danh sách! Mảng được ghim này thay đổi kích thước của nó khi chúng tôi thu nhỏ hoặc khôi phục chế độ xem ở chế độ xem Test1
! Một lần nó là 16 bài và lần sau là 69 mục khi được lược tả.
Điều này có nghĩa WPF thực hiện ghim các hạng mục được tạo ra trong mục kiểm soát! Bất cứ ai có thể giải thích điều này? Điều này có bất kỳ hạn chế đáng kể nào không?
Thx rất nhiều.
Có lẽ một 'CollectionView' tạo ra cho bộ sưu tập được treo xung quanh. – user7116
thx cho phản hồi. Vâng! Đây là bộ sưu tập các vật phẩm từ vật phẩm chứa. Nhưng tại sao sẽ là treo xung quanh? Chế độ xem đã biến mất. ListBox đã biến mất. Tại sao WPF sẽ thu thập các bộ sưu tập trong memeory? –
Bạn có thể đăng gốc cho ví dụ đã ghim không. –