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

GDI Handle leak #22

Closed
LordRiffRaff opened this issue Mar 16, 2016 · 7 comments
Closed

GDI Handle leak #22

LordRiffRaff opened this issue Mar 16, 2016 · 7 comments

Comments

@LordRiffRaff
Copy link

There's a GDI handle leak in frames. (It's more obvious if you've got some gif images with hundreds of frames in them as when you hit ~10K frames in your app, it'll crash).

To resolve this:

ImageBehaviour.cs -> MakeFrame

Line 674:
var bitmap = new RenderTargetBitmap(
fullSize.Width, fullSize.Height,
96, 96,
PixelFormats.Pbgra32);
bitmap.Render(visual);

        var result = new WriteableBitmap(bitmap);  

        if (result.CanFreeze && !result.IsFrozen)
            result.Freeze();
        return result;

WriteableBitmaps don't take up a GDI handle. RenderTargetBitmaps do.

Note this only resolves half of the issue though

Inside ImageBehaviour -> GetAnimation

line: 470:
animation.RepeatBehavior = GetActualRepeatBehavior(imageControl, decoder, gifMetadata);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Reason for the GC WaitForPendingFinalizers is that the GDI Handle gets disposed in the Finalizer which might not happen before the 10K limit gets breached. (i.e the GC doesn't know about the GDI limit and can let it go over the limit causing an app crash). Sorry it's not in a pull request but my current environment I don't have permissions to install GIT.

@thomaslevesque
Copy link
Member

Hi,

Thanks for reporting the issue. I'll look into it as soon as I can.

@mivor
Copy link

mivor commented Sep 27, 2017

Hi,

Any updates on this? I'm also having crashes because of the GDI leak.

@thomaslevesque
Copy link
Member

Hi,

Sorry @LordRiffRaff for taking so long before getting back to you, and thanks @mivor for reminding me ;)

The WriteableBitmap trick does seem to keep the GDI handle count at more reasonable level. I'll publish a release with this fix shortly.
I'm wary about running a full GC every time an animation is loaded, though... it can have a pretty heavy impact on application performance, and I don't want to penalize the vast majority of users who are not affected by the problem by forcing a full GC on them.

thomaslevesque added a commit to thomaslevesque/WpfAnimatedGif that referenced this issue Sep 27, 2017
@LordRiffRaff
Copy link
Author

Yeah, the GC hit can be jarring. In my use case I didn't care as it was for a kiosk, so once the app has started up you no longer care. The only problem though is that without it, it'll crash randomly. I'm not aware of a way to force the finalizer of the RenderTargetBitmap otherwise. https://stackoverflow.com/questions/13954829/gc-collect-and-finalize

Maybe an app config settings?

Then again, it may be only me and @mivor who've ended up with projects with gifs with tens of thousands of frames.

@thomaslevesque
Copy link
Member

gifs with tens of thousands of frames.

Really?! 😲
OK, this might be a dumb question, but why not use a video instead? The GIF format was never intended for very long animations...

Anyway, I just released 1.4.15, which includes the WriteableBitmap fix.

@mivor
Copy link

mivor commented Sep 27, 2017

Thanks for the quick fix. I will check tomorrow how it performs.
In my case the gif is definetly smaller.
I have the same gif animated in 6-10 places in one screen, for a loading animation.

@LordRiffRaff
Copy link
Author

03_cheesepyramid
05_picnicbasket

Transparency, and the animation house exported them all as gifs. In the end I wrote a pixel shader to do transparent chromakey video for the large animations (i.e the ones that were 200x200 pixels).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants