由于System.Windows.EffectiveValueEntry而未处置对象

时间:2013-03-06 15:54:42

标签: c# wpf

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

如果集合未绑定到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>

1 个答案:

答案 0 :(得分:4)

这可能已经很晚了,但我认为你的问题不在于EffectiveValueEntry,而在于你的Snapshot类。

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

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

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