为什么我得到一个OutOfMemoryException当我在我的列表框的图片? [英] Why do I get an OutOfMemoryException when I have images in my ListBox?

查看:140
本文介绍了为什么我得到一个OutOfMemoryException当我在我的列表框的图片?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要显示它采用了的ListBox 显示图像。

I want to display all images stored in the Windows Phone 8 photo folder in my custom gallery which uses a ListBox for displaying the images.

的ListBox code是如下:

    <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();
    }
}

图像存储在自定义类:

Images are stored in a custom class:

class PreviewImageItem
{
    public Picture _picture = null;
    public BitmapImage _bitmap = null;

    public PreviewImageItem(Picture pic)
    {
        _picture = pic;
    }

    public BitmapImage ImageData 
    {
        get
        {
            System.Diagnostics.Debug.WriteLine("Get picture " + _picture.ToString());
            _bitmap = new BitmapImage();
            Stream data = _picture.GetImage();
            try
            {
                _bitmap.SetSource(data); // Out-of memory exception (see text)
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Exception : " + ex.ToString());
            }
            finally
            {
                data.Close();
                data.Dispose();
                data = null;
            }

            return _bitmap;
        }
    }
}

以下code是用来设置的ListBox 数据源:

private List<PreviewImageItem> _galleryImages = new List<PreviewImageItem>();

using (MediaLibrary library = new MediaLibrary())
{
    PictureCollection galleryPics = library.Pictures;
    foreach (Picture pic in galleryPics)
    {
        _galleryImages.Add(new PreviewImageItem(pic));
    }

    previewImageListbox.ItemsSource = _galleryImages;
};

最后,这里是清理code:

Finally here is the "cleanup" code:

private void VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1(object sender, CleanUpVirtualizedItemEventArgs e)
{
    PreviewImageItem item = e.Value as PreviewImageItem;

    if (item != null)
    {
        System.Diagnostics.Debug.WriteLine("Cleanup");
        item._bitmap = null;
    }
}

这一切工作正常,但在code崩溃与 OutOfMemoryException异常经过短短的图像(尤其是快速滚动时)。该方法 VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1 被称为regulary(例如每2或3列表框项)当的ListBox 滚动。

All this works fine but the code crashes with an OutOfMemoryException after a few images (especially when scrolling fast). The method VirtualizingStackPanel_CleanUpVirtualizedItemEvent_1 is called regulary (e.g. every 2 or 3 listbox entries) when the ListBox is scrolled.

这有什么错此示例code?

What's wrong with this sample code?

为什么不内存释放(不够快)?

Why is memory not freed (fast enough)?

推荐答案

呵呵,我最近被杀害整天做这个工作!

Oh, I recently killed whole day to make this working!

所以,解决的办法是:

请您的图像控制的资源。所以设置

Make your Image control free resources. So set the

BitmapImage bitmapImage = image.Source as BitmapImage;
bitmapImage.UriSource = null;
image.Source = null;

,因为它是前文所述。

as it was mentioned before.

请确保您虚拟化_bitmap上的列表中的每一个项目。你应该将其加载点播(LongListSelector.Realized法),你必须摧毁它!它会不会自动收集和GC.Collect的也不管用。
空引用是不是工作压力太大:(
但这里是方法:
制作1x1像素的文件。它复制到组装并从中资源流与1x1像素的空白处置图像。定制绑定处置方法LongListSelector.UnRealized事件(e.Container处理您的列表项)。

Make sure you virtualize _bitmap on every item of the list. You should load it on demand (LongListSelector.Realized method) and you have to destroy it! It won't going to collect automatically and GC.Collect doesn't work either. Null reference is not working too :( But here is the method: Make 1x1 pixel file. Copy it into assembly and make resource stream from it to dispose your images with 1x1 pixel blank. Bind custom dispose method to LongListSelector.UnRealized event (e.Container handles your list item).

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宽度每个。

Working for me in LongListSelector with 1000 images 400 width each.

如果你错过了2步与数据收集可以看到的好成绩,但之后100-200项目滚动内存溢出。

If you miss the 2 step with the data collection you can see the the good results but the memory overflows after 100-200 items scrolled.

这篇关于为什么我得到一个OutOfMemoryException当我在我的列表框的图片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆