为了账号安全,请及时绑定邮箱和手机立即绑定

当列表框中有图像时,为什么会出现OutOfMemoryException?

当列表框中有图像时,为什么会出现OutOfMemoryException?

C#
鸿蒙传说 2019-12-02 10:59:03
我想在我的自定义库中ListBox显示Windows Phone 8照片文件夹中存储的所有图像,该文件夹用于显示图像。的ListBox代码如下:    <phone:PhoneApplicationPage.Resources>        <MyApp:PreviewPictureConverter x:Key="PreviewPictureConverter" />    </phone:PhoneApplicationPage.Resources>    <ListBox Name="previewImageListbox" VirtualizingStackPanel.VirtualizationMode="Recycling">        <ListBox.ItemsPanel>            <ItemsPanelTemplate>                <VirtualizingStackPanel CleanUpVirtualizedItemEvent="VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1">                </VirtualizingStackPanel>            </ItemsPanelTemplate>        </ListBox.ItemsPanel>        <ListBox.ItemTemplate>            <DataTemplate>                <Grid>                    <Image Source="{Binding Converter={StaticResource PreviewPictureConverter}}" HorizontalAlignment="Center" VerticalAlignment="Center" />                </Grid>            </DataTemplate>        </ListBox.ItemTemplate>     </ListBox>使用以下转换器:public class PreviewPictureConverter : System.Windows.Data.IValueConverter{    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        PreviewImageItem c = value as PreviewImageItem;        if (c == null)            return null;        return c.ImageData;    }    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        throw new NotImplementedException();    }}图像存储在自定义类中:class PreviewImageItem{    public Picture _picture = null;    public BitmapImage _bitmap = null;    public PreviewImageItem(Picture pic)    {        _picture = pic;    }所有这些都可以正常工作,但是代码OutOfMemoryException在显示几张图像后崩溃(特别是在快速滚动时)。滚动VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1时,该方法称为常规(例如,每2或3个列表框条目)ListBox。此示例代码有什么问题?为什么没有释放内存(足够快)?
查看完整描述

3 回答

?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

哦,最近我整天杀了这个,使它正常工作!


所以解决方案是:


使您的图像控件免费资源。所以设置


BitmapImage bitmapImage = image.Source as BitmapImage;

bitmapImage.UriSource = null;

image.Source = null;

如前所述。


确保在列表的每个项目上虚拟化_bitmap。您应该按需加载它(LongListSelector.Realized方法),并且必须销毁它!它不会自动收集,并且GC.Collect也不能工作。空引用也不起作用:(但是这里是方法:制作1x1像素文件。将其复制到程序集中并从中获取资源流以处置1x1像素为空白的图像。将自定义处置方法绑定到LongListSelector.UnRealized事件(e。容器处理您的列表项)。


public static void DisposeImage(BitmapImage image)

{

    Uri uri= new Uri("oneXone.png", UriKind.Relative);

    StreamResourceInfo sr=Application.GetResourceStream(uri);

    try

    {

        using (Stream stream=sr.Stream)

        {

            image.DecodePixelWidth=1; //This is essential!

            image.SetSource(stream);

        }

    }

    catch { }

}

在LongListSelector中为我工作,每个图像有1000张宽度为400的图片。


如果您错过了数据收集的第2步,则可以看到良好的结果,但是在滚动100-200个项目后内存溢出。


查看完整回答
反对 回复 2019-12-02
  • 3 回答
  • 0 关注
  • 483 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信