3

I have created a pivot that dynamically download and hold several large images. I first download the image using webclient and write it into disk. than create an array of image list that holds all the images. The basic idea is that I only load images when it is needed. Say there is 12 images in my list. Pivot is showing only 1 image per slide. Assume we are viewing image 7. I proceed to preload image 6 & 8 for next slides.

1, 2, 3, 4, 5, [6, {7}, 8], 9, 10, 11, 12

When user navigate through slides, I keep the image preloaded between and unload outside "[ ]".

The code I used to preload image:

BitmapImage bi = new BitmapImage();
bi.SetSource(GetStream(fileName);
IMGSource = bi; // IMGSource<ImageSource> referenced by the xaml in Image Binding IMGSource.

The code I used to unload images:

IMGSource = null;
GC.Collect(); // I force the program to Garbage collect since the image is really large.

The problem is, after several image is viewed(about 9 image). It throws an OutOfMemory exception in the line: bi.SetSource.

I checked that the unload function had worked properly( it does released the memory after calling Collect, and memory kept at a steady point)

But it still throws an OutOfMemory exception. What should I do?

Edit:
I just discovered that the memory in fact keeps going up
when navigating through slides. By calling:

Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage;

It gives the memories like:

54.7 MB, 76.91 MB, 111.94 MB, 105 MB, 112.71 MB, 141.93 MB, 148.42 MB, Exception thrown

But by calling:

GC.GetTotalMemory(false);

It is showing around 1.2~1.3 MB only.
What happened? Shouldn't the memory being released?

user1510539
  • 581
  • 1
  • 6
  • 17
  • Please be more sensitive about [formatting](http://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks) – Soner Gönül Feb 16 '13 at 18:26
  • Sorry I am using my phone to post. It doesn't have a preview for me and I did typed four spaces for codes. But it turns out it didn't worked:\ – user1510539 Feb 16 '13 at 18:29
  • 1
    That may not be the source of the leak, but you should make sure that you close the stream after loading the picture: `using (var stream = GetStream(fileName)) { bi.SetSource(stream); }` – Kevin Gosse Feb 16 '13 at 19:20
  • Just tested, closing the stream doesn't work. It still throws the exception. – user1510539 Feb 17 '13 at 03:43

1 Answers1

1

I end up with setting an Empty 1x1 transparent GIF to the image source the release the memory.

public static byte[] EMPTY_IMAGE = new byte[]{
    71, 73, 70, 56, 57, 97, 1, 0, 1
    , 0, 128, 0, 0, 255, 255, 255
    , 0, 0, 0, 33, 249, 4, 1, 0, 0
    , 0, 0, 44, 0, 0, 0, 0, 1, 0, 1
    , 0, 0, 2, 2, 68, 1, 0, 59
};

And then just use:

bi.SetSource(new System.IO.MemoryStream(MYCLASS.EMPTY_IMAGE));

And the memory seems released properly.

user1510539
  • 581
  • 1
  • 6
  • 17
  • Rather than a 1x1 GIF, you can use a fake picture and catch the exception: http://stackoverflow.com/a/13482619/869621 – Kevin Gosse Feb 17 '13 at 09:14
  • Also, if you don't mind, could you try setting UriSource to null as explained here: http://stackoverflow.com/a/13963747/869621 and see if it works? – Kevin Gosse Feb 17 '13 at 09:24
  • I tried to use new byte[]{0x0} but it thrown me an execption. So that's why I use 1x1 GIF. – user1510539 Feb 17 '13 at 09:29
  • I think UriSource is only available when the source is URI. In my case, the source is a stream from isolated storage. Thus setting the UriSource may not work since the source is a direct stream. – user1510539 Feb 17 '13 at 09:32