Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak in WPF GDI Control #45

Closed
andulv opened this issue Apr 18, 2014 · 1 comment
Closed

Memory leak in WPF GDI Control #45

andulv opened this issue Apr 18, 2014 · 1 comment
Assignees
Labels
area-rendering Everything related to the rendering 🕷️ type-bug state-accepted This is a valid topic to work on.

Comments

@andulv
Copy link

andulv commented Apr 18, 2014

While using the control in a WPF project I ran into various out-of-memory exceptions after rendering several Scores.

It seems like memory for the previous generated bitmap is not released when a new bitmap is generated.

The code below is taken from OnRenderFinished in AlphaTabGdi.cs:

        using (Bitmap bitmap = ((GdiCanvas)_renderer.canvas).getImage())
        {
            Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                bitmap.GetHbitmap(),
                IntPtr.Zero, Int32Rect.Empty,
                BitmapSizeOptions.FromWidthAndHeight(bitmap.Width, bitmap.Height));
            Width = bitmap.Width;
            Height = bitmap.Height;
        }

As far as I have understood, the call to bitmap.GetHbitmap() gives a pointer to unmanaged memory that must be freed after use.

I applied the following quick-fix / workaround.

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

    IntPtr _currentlyAllocatedBitmap = IntPtr.Zero;

    // This method raises the Tap event 
    protected virtual void OnRenderFinished()
    {
        using (Bitmap bitmap = ((GdiCanvas)_renderer.canvas).getImage())
        {
            if (_currentlyAllocatedBitmap != IntPtr.Zero) 
             {
                DeleteObject(_currentlyAllocatedBitmap);
                _currentlyAllocatedBitmap=  IntPtr.Zero;
             }

            _currentlyAllocatedBitmap=bitmap.GetHbitmap();
            Source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                _currentlyAllocatedBitmap,
                IntPtr.Zero, Int32Rect.Empty,
                BitmapSizeOptions.FromWidthAndHeight(bitmap.Width, bitmap.Height));

            Width = bitmap.Width;
            Height = bitmap.Height;
        }

        RoutedEventArgs newEventArgs = new RoutedEventArgs(RenderFinishedEvent);
        RaiseEvent(newEventArgs);
    }

This quick-fix is far from perfect, and memory may probably still leak in some cases, but it solved the problems I were experiencing.

@Danielku15
Copy link
Member

Thanks for the fix. I will take a look if there's a better solution to convert a GDI Bitmap into a WPF Image which allows immediate cleanup of the GDI stuff. I probably could copy the raw Bitmap Data into a WritableBitmap to resolve this problem but we'll see.

@Danielku15 Danielku15 self-assigned this Apr 19, 2014
Danielku15 added a commit that referenced this issue Apr 19, 2014
Fixed memory leak in WPF GDI Control (fixes #45)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-rendering Everything related to the rendering 🕷️ type-bug state-accepted This is a valid topic to work on.
Projects
None yet
Development

No branches or pull requests

2 participants