Hi all,
I am wondering if there is a .net `EventHandler` leak surrounding CroppedBitmap and RenderTargetBitmap. It's causing me a huge nightmare!
My WPF app runs an always running render call at 60fps. I noticed that after a time, the content being rendered got slower and slower and slower.
After much investigation, including profiling in visual studio and using ANTS memory profiler, I narrowed it down to using a CroppedBitmap.
I've got some simple `demonstration of problem` code, which includes...
RenderTargetBitmap srcBitmap = new RenderTargetBitmap((int)scaledWidth, (int)scaledHeight, 96, 96, PixelFormats.Default); RenderTargetBitmap destBitmap = new RenderTargetBitmap((int)scaledWidth, (int)scaledHeight, 96, 96, PixelFormats.Default);<code loop> {... DrawingVisual DV = new DrawingVisual(); DrawingContext DC = DV.RenderOpen(); var srcRec = new Int32Rect(x,y,w,h); var srcCrop = new CroppedBitmap(srcBitmap, srcRec); var destRec = new Rect(.....); DC.DrawImage(srcCrop, destRec); DC.Close(); destBitmap.Render(DV); DC = null; DV = null; ...}
After CroppedBitmap is called using srcBitmap, srcBitmap has an event handler added to it. Not to sure what exactly, or where from, but it appears to be within the .net framework on the unmanaged side of things.
Spotting climbing number of event instances. Same sort of thing visible in visual studio when profiling.
Checking out what's referencing what...
CroppedBitmap has DownloadCompleted, DownloadFailed, DownloadProgress events. I would make a guess it's the DownloadCompleted.
Checking the number of EventHandlers (using the _downloadEvent property on the srcBitmap/RenderTargetBitmap), this is indeed increasing by one each time CroppedBitmap is called - and never goes down. I can only come to the conclusion that CroppedBitmap is adding an event handler to the RenderTargetBitmap which is never getting removed. After running for a while, this ends up with x000's of event handlers on the RenderTargetBitmap, which I presume .net is going through and causing my speed degradation.
I can't for the life of me work out what to do about this! The image is being set on a simple Image control, nothing fancy.
Content.Source = srcBitmap;
....
<Image x:Name="Content" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderOptions.BitmapScalingMode="LowQuality" Stretch="None" IsHitTestVisible="False"></Image>
Just to be clear, as an example the code can run with no rendering, no draw image etc, - just thenew CroppedBitmap... code is needed to show this behaviour. The other lines were included above for completeness.
The above example was run against .NET Framework 4.7.2 to make sure the latest version had this problem.
I also tried Freezing the CroppedBitmap, just in case that made a difference. Apparently not. In fact, callingsrcCrop.Freeze resulted in srcBitmap.isFrozen being true! erm..... so it seems CroppedBitmap makes alterations to the bitmap it is being cropped against?
Couldn't find any information, help, articles etc. on the above :(
Anyone any ideas what I might be able to do to fix this leak?
Thanks for your help in advance...
Martin