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

我想在我的自定义库中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。


此示例代码有什么问题?


为什么没有释放内存(足够快)?


鸿蒙传说
浏览 485回答 3
3回答

至尊宝的传说

哦,最近我整天杀了这个,使它正常工作!所以解决方案是:使您的图像控件免费资源。所以设置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){&nbsp; &nbsp; Uri uri= new Uri("oneXone.png", UriKind.Relative);&nbsp; &nbsp; StreamResourceInfo sr=Application.GetResourceStream(uri);&nbsp; &nbsp; try&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; using (Stream stream=sr.Stream)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image.DecodePixelWidth=1; //This is essential!&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image.SetSource(stream);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; catch { }}在LongListSelector中为我工作,每个图像有1000张宽度为400的图片。如果您错过了数据收集的第2步,则可以看到良好的结果,但是在滚动100-200个项目后内存溢出。
打开App,查看更多内容
随时随地看视频慕课网APP