0

I'm implementing a small imageviewer, unfortunately I'am facing a memory leak. Following is my loading routine.

 public BitmapSource getImage(string fileName, double width, double height)
    {
        FileStream s = File.Open(fileName, FileMode.Open);
        Image i = Image.FromStream(s, false, false);
        double iWidth = i.Width;
        double iHeight = i.Height;
        i.Dispose();
        s.Close();

        BitmapImage tmpImage = new BitmapImage();
        tmpImage.BeginInit();
        tmpImage.CacheOption = BitmapCacheOption.OnLoad;
        tmpImage.UriSource = new Uri(fileName);
        if (iWidth > iHeight)
        {
            tmpImage.DecodePixelWidth = (int)width;
        }
        else
        {
            tmpImage.DecodePixelHeight = (int)height;
        }
        tmpImage.EndInit();
        return tmpImage;
    }

This is how I call the loader

private void whenArrowKeyPressed(int index)
{
   CurrentImage =  fh.getImage(fileList[index], 1920, 1080);
}

CurrentImage is a property, which is bound to a WPF ViewBox.

Any Ideas? I also tried to read from StreamSource, with the same effect.

JustMe
  • 366
  • 1
  • 4
  • 14
  • You're not disposing the FileStream. Call s.Dispose() instead of s.Close(); Dispose will take care of the close also. – Jeff Prince Aug 21 '15 at 15:40
  • Thanks, I could see some improvement. Unfortunately, it is not solving the issue completely. When showing the first image, the application uses ca. 150MB, after switching several times, I see now a raise to ca, 300MB – JustMe Aug 21 '15 at 15:44
  • I think your problem must be in some code you haven't posted. I don't see anything else wrong in the code you have posted. – Jeff Prince Aug 21 '15 at 15:54
  • And, by the way, you might want to read this: http://stackoverflow.com/questions/9175755/still-memory-leaks-in-net4-binding-memory-bitmapimage-to-image-source?rq=1. – Jeff Prince Aug 21 '15 at 15:56
  • Thanks. I will also check the remainig code. – JustMe Aug 21 '15 at 18:08

1 Answers1

0

Only issue I could see is you are not disposing you FileStream. BitmapImage is not Disposable and it will release its memory if there are no references to it.

How did you find there is a memory leak? It’s recommended to use a profiling tool. Garbage collector doesn't release memory immediately something goes out of scope, it waits until memory usages exceeds certain thresholds (usually when Gen 0 going to exceed the threshold). So, you will see some memory increase and it will release memory only after garbage collector executes.

Apparently you are not using a profiling tool. In this case if you want to check if there is any memory leak, you can manually execute GC.Collect and wait for finalization before you get memory reading. Keep in mind that you don’t have to execute GC.Collect manually as it will occur automatically in an optimized way when required.

    public BitmapSource getImage(string fileName, double width, double height)
    {
        using(FileStream s = File.Open(fileName, FileMode.Open))
        using(Image i = Image.FromStream(s, false, false))
        {
            double iWidth = i.Width;
            double iHeight = i.Height;                
        }

        BitmapImage tmpImage = new BitmapImage();
        tmpImage.BeginInit();
        tmpImage.CacheOption = BitmapCacheOption.OnLoad;
        tmpImage.UriSource = new Uri(fileName);
        if (iWidth > iHeight)
        {
            tmpImage.DecodePixelWidth = (int)width;
        }
        else
        {
            tmpImage.DecodePixelHeight = (int)height;
        }
        tmpImage.EndInit();
        return tmpImage;
    }

private void whenArrowKeyPressed(int index)
{
   CurrentImage =  fh.getImage(fileList[index], 1920, 1080);

   // Remove this once you finish testing.
   GC.Collect();
   GC.WaitForPendingFinalizers();
}
CharithJ
  • 46,289
  • 20
  • 116
  • 131