5

我有一个 ObservableCollectionSnapshot对象,绑定到 ListBox 的 ItemsSource。如果一个新Snapshot对象被推入集合并且集合已经包含 3 个元素,Snapshot则删除最后一个对象。然而,被移除的对象永远不会被 GC 收集。为了验证这一点,我GC.Collect()在从集合中删除了一个对象并使用 YourKit Profiler 分析了我的应用程序后调用了它。创建 6 个Snapshot对象后,YourKit Profiler 制作了内存快照。尽管集合仅引用了 3 个对象,但所有 6 个Snapshot对象仍然存在。System.Windows.EffectiveValueEntry 引用了其他 3 个。

当集合未绑定到 ListBox 的 ItemsSource 时,Snapshot将按预期收集对象。

如何摆脱 System.Windows.EffectiveValueEntry 的引用?

public class Snapshot
{
    public BitmapImage PreviewImage { get; set; } // Freezed BitmapImage
    public string Path { get; set; }
    public string Name
    {
        get
        {
            return System.IO.Path.GetFileNameWithoutExtension(Path);
        }
    }
}

XAML:

<ListBox ItemsSource="{Binding Path=LastCapturedPictures}"
                 SelectedItem="{Binding Path=SelectedCapturedPicture}" HorizontalAlignment="Stretch"
                 Margin="0,2,0,0" Grid.Column="1" Grid.Row="3">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Vertical" VerticalAlignment="Center"
                                HorizontalAlignment="Left"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="5,0,5,0">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Image Source="{Binding Path=PreviewImage}" Width="130" Height="100"
                               Margin="0,0,0,2" Grid.Row="0" HorizontalAlignment="Left">
                            <Image.BitmapEffect>
                                <DropShadowBitmapEffect/>
                            </Image.BitmapEffect>
                        </Image>
                        <TextBlock Text="{Binding Path=Name}" Margin="0,2,0,0" Grid.Row="1"
                                   TextAlignment="Left"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
4

1 回答 1

7

这可能为时已晚,但我认为您的问题不在于 EffectiveValueEntry,而在于您的 Snapshot 类。

如果要绑定到此类,则应实现 INotifyPropertyChanged 接口。

我不完全了解 WPF 的内部工作原理,但是当使用像 ANTS 这样的内存分析器时,您可以看到与对象大不相同的保留图。

例如,您的 Snapshot 类当前将导致 WPF 为您通过反射在 XAML 中绑定到的每个属性创建 ValueChanged 事件处理程序,并且这些属性没有正确清理。当您实现 INotifyPropertyChanged 时,这不会发生,并且绑定会自行清理属性。

于 2014-02-21T11:23:44.233 回答