加载BitmapImage在WP 8.1 RT中占用大量内存

时间:2015-11-24 14:03:58

标签: c# memory-leaks windows-runtime windows-phone-8.1 winrt-xaml

我正在使用Windows Phone 8.1 RT应用程序。从文件中读取图像后显示图像的一种方法是创建BitmapImage并将其设置为XAML Image控件的源。

我正在使用以下代码执行相同操作。图像存储在LocalFolder

private async void LoadImage()
{
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile file = await folder.GetFileAsync("imageFile.jpg");

    BitmapImage bitmapImage = new BitmapImage();

    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
    { 
        bitmapImage.DecodePixelWidth = 500;
        await bitmapImage.SetSourceAsync(stream);
    }

    imageHolder.Source = bitmapImage;
}

由于我正在加载图像的一小部分,因此我使用DecodePixelWidth来节省内存。但是,我的观察结果并不符合预期。

观察:

  1. 如果我将40 MB图像加载到内存中,则应占用的内存应增加大约40 MB(加上任何开销内存增加),但应用程序的内存分析会另外说明。我看到当加载320 MB图像时,内存会上升到40 MB

  2. 如果我使用DecodePixelHeightDecodePixelWidth来节省内存,内存仍会高达50-80MB(大于原始图片的大小),具体取决于{{ {1}} / DecodePixelHeight

  3. 我希望操作系统能够明智地使用内存,并在加载图像时使用最少的内存。我预计操作系统在设置DecodePixelWidth时使用的内存少于40 MB,但是看到实际结果时非常惊讶。

    有人可以解释为什么在将图像加载到内存时会使用如此大量的内存吗?这是预期的行为吗?我可以做些什么来节省内存,因为如果事情是这样的话,我无法在没有获得OOM的情况下同时将两个大图像加载到内存中,即使使用DecodePixelWidth也是如此。

    附加了分析截图。

    1. 不使用DecodePixelWidth,图片大小DecodePixelWidth第一个峰值为40 MB.,第二个峰值为245 MB
    2. enter image description here

      1. 使用327 MB,图片大小DecodePixelWidth = 500。第一个峰值为40 MB,持续水平为88 MB
      2. enter image description here

1 个答案:

答案 0 :(得分:1)

您可以通过IRandomAccesStream创建BitmapImage,而不是通过StorageFile创建压缩的缩略图。

StorageItemThumbnail thumb =  file.GetScaledImageAsThumbnailAsync(ThumbnailMode.ListView, 
                                                                  90,
                                                                  ThumbnailOptions.UseCurrentScale);
        var bitmap = new BitmapImage();
        bitmap.SetSource(thumb);

这会直接从流中创建一个比普通BitmapImage小得多的BitmapImage。

此外,如果您需要加载大量图像,则应查看虚拟化甚至增量列表。