0

I'm trying to copy some pictures to RAM but this leads to a Out of Memory Exception.. I don't know why but I think it's cause of the "freeze()". But how to "unfreeze" and is this really the problem?

        public void preLoadThread(Object o)
    {
        Overlay ov = (Overlay)o;
        ImageSource tempNext = BitmapConverter(ov.tempPreLoadPathNext);
        ImageSource tempPrev = BitmapConverter(ov.tempPreLoadPathPrev);
        tempNext.Freeze();
        tempPrev.Freeze();
        ov.Dispatcher.Invoke(
            DispatcherPriority.Normal,
            (Action)delegate()
            {
                ov.preLoadedNext = tempNext;
                ov.preLoadedPrev = tempPrev;
                ov.preLoadPathNext = ov.tempPreLoadPathNext;
                ov.preLoadPathPrev = ov.tempPreLoadPathPrev;
            }
        );
    }

    public BitmapSource BitmapConverter(String path)
    {
        System.Drawing.Bitmap b = null;
        using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
        {
            try
            {
                b = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(fs);
            }
            catch (Exception)
            {
                GC.Collect();
                GC.WaitForFullGCComplete();
            }
            fs.Close();
        }

        if ( b == null)
        {
            // Error
            return null;
        }

        BitmapSizeOptions options = BitmapSizeOptions.FromEmptyOptions();
        BitmapSource bs = null;
        try
        {
            bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
               b.GetHbitmap(),
               IntPtr.Zero,
               Int32Rect.Empty,
               options);
        }
        catch (Exception)
        {
            GC.Collect();
            GC.WaitForFullGCComplete();
        }
        return bs;
    }
martinyyyy
  • 1,652
  • 3
  • 21
  • 44

2 Answers2

1

I sincerely doubt the memory exception is coming from the Freeze() call, as that really isn't allocating any memory.

I'm pretty sure you have a GDI leak... You have to call DeleteObject on the bitmap you create after you call CreateBitmapSourceFromHBitmap()... but because you're calling GetHbitmap() as a parameter, you have no handle to delete.

Try this:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

...

IntPtr hObject = b.GetHbitmap();
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
           hObject,
           IntPtr.Zero,
           Int32Rect.Empty,
           options);

DeleteObject(hObject);


Henk is right, you shouldn't be forcing a GC collection... it's not really helping you, because you're not really freeing anything to be collected, anyway (the only thing you're freeing has to be cleaned up via DeleteObject().

How many 1378x2000 images are we talking about? Even if you fix your GDI leak, those are big pictures and will eat up memory quickly.

Curtisk is right, you can't unfreeze, you have to clone... but you'll be allocating memory when you do so. Just to warn you.

I suppose running under 64-bit isn't an option...

James King
  • 6,233
  • 5
  • 42
  • 63
  • What is `DeleteObject()`? Am I missing a reference? – Mateen Ulhaq Apr 15 '16 at 18:36
  • It's a declaration to a call in the `gdi32.dll` DLL (part of Windows). The attribute above the declaration tells .NET to import that DLL at runtime, and tells it where to look for the `DeleteObject()` call in the code. Be warned, you're calling unmanaged code, and there are a number of implications there. Link to more info: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute%28v=vs.110%29.aspx – James King Apr 17 '16 at 20:26
0

As far as your "unfreeze" question, you can't on the initial item but you can spin off an unfrozen clone, details and example at MSDN

curtisk
  • 19,950
  • 4
  • 55
  • 71