-1

I am currently very confused about my app :( . My app is taking up too much of memory..

Basically my app is a WPF application and it has 3-4 windows and a few pages,each one is opened/displayed when/as required.Each window/page has a couple of Image controls to display images.To retrieve the images(from resource),i am using the following function :

public BitmapImage LoadImage(Uri uri, bool LoadOnMemory, int Pixel)
{
if (LoadOnMemory == true)
{
    System.Windows.Resources.StreamResourceInfo sri = Application.GetResourceStream(uri);
    System.IO.BinaryReader binReader = new System.IO.BinaryReader(sri.Stream);
    byte[] buffer = binReader.ReadBytes(sri.Stream.Length);
    using (MemoryStream memoryStream = new MemoryStream(buffer))
    {
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.Default;
        bi.CreateOptions = BitmapCreateOptions.None;
        bi.StreamSource = memoryStream;
        bi.DecodePixelWidth = Pixel;
        bi.EndInit();
        bi.Freeze();
        return bi;
    }
}
else
{
    BitmapImage bi = new BitmapImage();
    bi.BeginInit();
    bi.CacheOption = BitmapCacheOption.Default;
    bi.CreateOptions = BitmapCreateOptions.None;
    bi.UriSource = uri;
    bi.DecodePixelWidth = Pixel;
    bi.EndInit();
    bi.Freeze();
    return bi;
}
}

I have,maybe like 20 images in total and to load each image,the function is called setting Pixel to 30(or sometimes 40) and LoadOnMemory to True.My startup window has 2 images and one TextBlock,same function is called to load both the images.

As soon as my app launches, in the Task Manager,i see that even the splash screen with only 2-3 lines of code to load the MainWindow is eating up 105+ mb of RAM.When my MainWindow loads,the consumption of RAM/Memory reaches upto 200+ mb.The main window calls the function couple o' times as there are almost 10 images in the MainWindow.From there on,no matter how many Pages or Windows with any amount of image i open,the consumption of RAM stays the same.It,for some reason,doesn't cross 220+ mb.

I was suspecting that as my function uses MemoryStream , this might be the reason for such a huge memory consumption.

But then i created a dummy window with no code-behind,just a blank window and launched my app......Even the blank window consumes 100+ mb of memory !!

But the dummy window is not my concern,my qs is , if for example, my app has like 20 images and each image is loaded using that function(or should i say the memorystream) , how much does it effect the ram ? (though i can see it's using almost 200+ mb).My function doesn't cause any lag/performance issue in the app but i just need to know if the function is responsible for such a huge memory consumption ?

UPDATE : Sorry for giving misleading info about the blank window

Till now i was running the app from within VS,so the total consumption of memory was actually the sum total of Intellitrace(eating up more than 30mb) and the Blank window(15-20 mb max....

One last qs, as i updated the code as well,which is better ? The 2nd part of the code(not using a memorystream) or the first part(using the memoryStream) in respect to both the app's performance and memory consumption ?

Software Dev
  • 5,368
  • 5
  • 22
  • 45
  • what you are seeing is #memoryleak because you never dispose the stream – Steve Mar 20 '18 at 16:16
  • will disposing the stream might solve the problem somewhat ? – Software Dev Mar 20 '18 at 16:17
  • try it yourself – Steve Mar 20 '18 at 16:17
  • but what abt the blank window ? it takes up 100+ mb of ram – Software Dev Mar 20 '18 at 16:18
  • Then go figure out all the places where you used an object that implements IDisposible and you did not call dispose or did not wrap it with 'using' – Steve Mar 20 '18 at 16:20
  • After you implementing the missing disposing of the stream and BinaryReader, you will also have to tell the BitmapImage to load the image data before the MemoryStream expires by using `BitmapCacheOption.OnLoad`. Also, why do you use a MemoryStream? You could directly assign sri.Stream as the image's StreamSource, no? –  Mar 20 '18 at 16:20
  • Thanks @elgonzo,i'll try it now :) ... But mind if i ask , is my post following all the rules ? Is it standard?(asking for future awareness) – Software Dev Mar 20 '18 at 16:23
  • There is nothing wrong with form or content of your question, in my opinion. –  Mar 20 '18 at 16:25
  • oke....can u please re-read my post.... – Software Dev Mar 20 '18 at 16:27
  • usually you should include minimum complete example instead of your own guess on what went wrong. Cuz most of the time your guess is wrong. But it seems like you got lucky this time. – Steve Mar 20 '18 at 16:27
  • @Steve, u mean my guess was right lol ? Anyway,can u take a look at my post again, i have added one last qs – Software Dev Mar 20 '18 at 16:28

1 Answers1

3

You certainly don't need an intermediate MemoryStream, when you could directly load the BitmapImage from the StreamResourceInfo's Stream:

private ImageSource LoadImage(Uri resourceUri, int pixelWidth)
{
    var resource = Application.GetResourceStream(resourceUri);
    var bitmap = new BitmapImage();

    using (var stream = resource.Stream)
    {
        bitmap.BeginInit();
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.StreamSource = stream;
        bitmap.DecodePixelWidth = pixelWidth;
        bitmap.EndInit();
        bitmap.Freeze();
    }

    return bitmap;
}

However, you don't need to use a Stream at all, which is apparently simpler:

private ImageSource LoadImage(Uri resourceUri, int pixelWidth)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.UriSource = resourceUri;
    bitmap.DecodePixelWidth = pixelWidth;
    bitmap.EndInit();
    bitmap.Freeze();
    return bitmap;
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • can u please tell me how much impact will your solution have on the consumption of memory and also on the performance ? – Software Dev Mar 20 '18 at 16:35
  • Try that yourself. My guess is that both should be very similar. – Clemens Mar 20 '18 at 16:37
  • before i implement this, what i wanted to know is, will this still have the same impact as the current function i have ? – Software Dev Mar 20 '18 at 16:37
  • 2
    Just try it. Unless you have a serious performance problem, you should use the most simple approach. – Clemens Mar 20 '18 at 16:38
  • Yep! It only takes 83mb now :) But can u please explain how it helped ? – Software Dev Mar 20 '18 at 16:41
  • @zackraiyan google memory leak and you will have all the answer you need. And yes you can cause memory leak in c# if you don't dispose IDisposible objects – Steve Mar 20 '18 at 16:52
  • 1
    @zackraiyan - *But can u please explain how it helped* not disposing disposables is probably the main reason. Another might be that the `byte []` array inside the `MemoryStream` went on the [large object heap](https://stackoverflow.com/q/8951836) which is not compacted by default. – dbc Mar 20 '18 at 17:59