-1

I'm seeing a huge memory leak in a program I'm building using WPF. I've written a small example app which seems to replicate this issue on a smaller scale.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        images = Directory.GetFiles("C:\\Photos", "*.jpg", 
                                                  SearchOption.TopDirectoryOnly);
        foreach (string image in images)
        {
            Window1 window = new Window1(image);
            window.Show();
            window.Close();
        }
    }
}

The Window1 XAML . . .

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    AllowsTransparency="True"
    WindowStyle="None"
    Background="White"
    Opacity="1.0"
<Grid>
    <Image Name="pb_Image"/>
</Grid>

. . . and the Window1 code

public Window1(string image)
    {
        InitializeComponent();
        BitmapImage bi = new BitmapImage(new Uri(image, UriKind.Absolute));
        bi.Freeze();
        pb_Image.Source = bi;
        pb_Image.Height = bi.Height;
        pb_Image.Width = bi.Width;
    }

It repeatedly shows and then closes a window which contains a BitmapImage however an "out of memory exception" occurs very quickly so I'm obviously doing something wrong and hoping someone can point it out!

* Update *

After playing around for a while I've isolated the issue, this causes a memory leak:

foreach (string image in images)
        {
            Window1 window = new Window1(image);
            window.Show();
            window.Close();
        }

and this doesn't

foreach (string image in images)
        {
            Window1 window = new Window1("C:\\Photos\\photo1.jpg");
            window.Show();
            window.Close();
        }

Puzzling - any ideas???

Gavimoss
  • 365
  • 2
  • 4
  • 22
  • 3
    Taskmgr is a *very* imperfect memory profiler, both the garbage collector and the Windows memory manager are far too sophisticated to be second-guessed by a single number. Prove that you have a real problem by running this code a million times. – Hans Passant Feb 18 '12 at 15:29
  • I've update my code to hopefully more accurately show what is happening. I suspect that my original scaled down code was not accurately reproducing the issue I am experiencing. – Gavimoss Feb 18 '12 at 16:51
  • check this one: http://stackoverflow.com/questions/568408/what-is-the-correct-way-to-dispose-of-a-wpf-window – Davide Piras Feb 18 '12 at 16:56
  • @DavidePiras thanks but I'm not sure what managed resources need to be disposed of and how I would do that. – Gavimoss Feb 18 '12 at 17:12
  • @Phil it's the image defined in the window xaml (see above edit) – Gavimoss Feb 18 '12 at 17:35
  • You may be correct about a memory leak http://microsoftdwayneneed.codeplex.com/discussions/245478 – Phil Feb 18 '12 at 17:49
  • Having said that I can't reproduce it. Are you on .NET 3.5 or 4? – Phil Feb 18 '12 at 17:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7889/discussion-between-gavimoss-and-phil) – Gavimoss Feb 18 '12 at 18:30
  • Then your issue must be one of the images in your list. It most definitely doesn't have anything to do with how you pass the string. Make sure you do not have some huge images. And I'm not talking size in bytes but resolution. Keep in mind a 10,000 x 10,000 white image in the jpeg format doesn't use much disk space, but once it loaded into `BitmapImage` it is converted into a 32bit bitmap, so the memory usage would be very high. – Terkel Feb 19 '12 at 00:39
  • @SimonBangTerkildsen The images I am using are quite large however the issue is with the memory not being released so not quite sure how what you are suggesting would cause this. Also, I created a folder with 200 copies of the same image (1600x1100 1.1MB) tried both loops as above and the same situation occurs so it's definitely not due to large images. – Gavimoss Feb 19 '12 at 11:38
  • Also tried on a folder of old phone images (160x120 3.2KB) so it's definitely not due to large images - has anyone else actually managed to replicate this? – Gavimoss Feb 19 '12 at 11:47

2 Answers2

0

Once you've close the window you still have a reference to the window object. You need to set window to null after you've closed it.

Terkel
  • 1,575
  • 8
  • 9
  • Removing all references to the window (e.g. setting `window = null`) only makes the `Window1` instance eligible for garbage collection. If and when it is collected and it's resources released is controlled by the garbage collector. Create a million windows as Hans Passant suggest and then see if resources are leaking. – Martin Liversage Feb 18 '12 at 15:36
  • I think my scaled down code isn't reflecting the issue I'm actually having so I've updated it to show more accurately what is happening. – Gavimoss Feb 18 '12 at 16:53
  • You've remembered to Freeze the bitmap, so I don't see any problems in your code (unless you images have a very high resolution, e.g. 10,000 x 10,000). As Martin and Hans, stated TaskManager is not good for any kind of memory profiling. I've used Redgates Ants memory profiler in the past, and I've found it easy to use, I suggest you download the trail version, in order to identify what exactly is causing your memory leak. – Terkel Feb 18 '12 at 18:40
  • @Gavimoss The best is to go for sos.dll. Run a dumpheap -stat when your program starts, leave it running for a while and run another dumpheap -stat. This will give you a clear indication of where the memory is used. – GETah Feb 19 '12 at 00:31
0

Not sure exactly why the above memory leak is occurring as from what I can determine, everything looks right.

I did manage to find this excellent tutorial on "WPF Multithreading - Using the BackgroundWorker and Reporting the Progress to the UI" which was easily adapted to cycle through and display a set of images without any kind of memory leak issues.

Gavimoss
  • 365
  • 2
  • 4
  • 22