DrawingContext.DrawText是否有内存泄漏?

时间:2012-11-27 23:37:02

标签: wpf

我有一个WPF应用程序,在特定模式下每隔0.5秒向UI显示一个文本字符串。我注意到,当发生这种情况时,内存使用量会缓慢而稳定地增加,而这种情况从未发布,如果我让它运行得足够长,它将耗尽内存并崩溃。

执行绘图的代码如下:

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

    ...
}    

文本在画布上绘制,其中包含以下代码部分:

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

我能够通过仅注释“dc.DrawText(...”行来“修复”此内存泄漏。这样做,应用程序的内存使用情况完全不变。除此之外,我不确定是什么尝试。我尝试搜索与DrawText相关的内存泄漏,但没有找到任何结果,我的函数中使用的代码几乎与用于DrawText的MSDN站点上的示例相同。

有没有人看过这个或看到我做错了什么?

  • 我尝试使用CLRProfiler,但我对它不是很熟悉,而且内存泄漏太慢,我无法从中获取任何有用的信息(可能缺乏对该工具的理解)。

1 个答案:

答案 0 :(得分:2)

因此,经过一些阅读和重新阅读后,我注意到此博客文章中的以下评论:https://blogs.msdn.com/b/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx?Redirected=true

“这只是版本3.5 SP1中出现的WPF泄漏。当在软件渲染模式下在Viewport3D中使用VisualBrush,WriteableBitmap或某些其他类时会发生这种情况。”

我正在使用Viewport,而不是Viewport3D,但我正在使用软件渲染,如果我按照帖子中的建议将VisualBrush更改为SolidColorBrush来测试泄漏,它就会消失。此外,从DrawingVisual转换为DrawingGroup也可以修复泄漏。

将第二个代码块更改为以下内容修复了泄漏:

DrawingVisual dg = new DrawingGroup();
var size = new Size( canvas.Width, canvas.Height );

using( DrawingContext dc = dg.Open() )
{
    // 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 DrawingBrush( dg );

我也尝试过使用DrawingVisual类对象并反复重复使用它,而不是每次绘制时都创建一个新对象,这也修复了泄漏。

编辑:我使用DrawingVisual的原因是它与我尝试的替代品(包括DrawingGroup)相比产生了最低的CPU使用率。差异并不大,但一致。