XamlAnimatedGif / WpfAnimatedGif

A simple library to display animated GIF images in WPF, usable in XAML or in code.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GDI Handle leak

LordRiffRaff opened this issue · comments

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.

Hi,

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

Hi,

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

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.

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.

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.

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.

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).