I have a WPF app that displays a text string to the UI every .5 seconds while in a certain mode. I noticed that when this happens there is a slow but steady increase in memory usage that is never released, and if I let it run long enough it will run out of memory and crash.
The code that does the drawing is below:
public void DrawDisplay( DrawingContext dc, Size size )
{
...
// Draw Text
var fontSize = 46.0;
FormattedText ft = new FormattedText(
message,
CultureInfo.GetCultureInfo( "en-us" ),
FlowDirection.LeftToRight,
new Typeface( "Franklin Book" ),
fontSize,
Brushes.Black );
ft.MaxTextWidth = size.Width - 2;
ft.TextAlignment = TextAlignment.Center;
// don't draw outside of box
ft.MaxTextHeight = size.Height;
// Center
var height = ( size.Height - ft.Height ) / 2;
dc.DrawText( ft, new Point( 0, height ) );
...
}
The text is drawn on a canvas with the following section of code:
DrawingVisual dv = new DrawingVisual();
var size = new Size( canvas.Width, canvas.Height );
using( DrawingContext dc = dv.RenderOpen() )
{
// draw a transparent rect so the text doesn't stretch (fixes size)
dc.DrawRectangle( Brushes.Transparent, null, new Rect( 0, 0, size.Width, size.Height ) );
RadioInterface.DrawDisplay( dc, size );
}
canvas.Background = new VisualBrush( dv );
I am able to “fix” this memory leak by commenting out only the “dc.DrawText(…” line. Doing this, the memory usage of the application is completely flat. Beyond this, I am not sure what to try. I tried searching for memory leaks related to DrawText but have found no results, and the code used in my function is almost identical to the example on the MSDN site for DrawText.
Has anyone seen this or see something that I am doing wrong?
- I tried using CLRProfiler but I am not very familiar with it and the memory leak is so slow I was not able to get any useful information out of it (possibly a lack of understanding the tool).
So after some more reading and re-reading, I noticed the following comment from this blog post: https://blogs.msdn.com/b/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx?Redirected=true
“This is a leak in WPF present in version 3.5 SP1 ONLY. This occurs when a VisualBrush, WriteableBitmap, or some select other classes are used within a Viewport3D in software rendering mode.”
I’m using a Viewport, not a Viewport3D, but I am using software rendering and if I change the VisualBrush to a SolidColorBrush as suggested in the post to test for the leak, it dissappears. Additionally, converting from a DrawingVisual to a DrawingGroup also fixes the leak.
Changing the second block of code to the following fixed the leak:
I also tried using a DrawingVisual class object and re-using it over and over instead of creating a new one each time I draw, and that also fixed the leak.
EDIT: The original reason I used DrawingVisual was it resulted in the lowest cpu usage compared to the alternatives I tried, including DrawingGroup. The difference wasn’t large, but it was consistent.