1

我有一个 WPF 程序,它使用 aCanvas内的 a Window,覆盖成为 a Graphics_Canvas,如下所示:

class Graphics_Canvas : Canvas
{
    private List<DrawingVisual> visuals = new List<DrawingVisual>();

    protected override int VisualChildrenCount
    {
        get { return visuals.Count; }
    }

    protected override Visual GetVisualChild(int index)
    {
        return visuals[index];
    }

    public void AddVisual(DrawingVisual visual)
    {
        visuals.Add(visual);

        base.AddVisualChild(visual);
        base.AddLogicalChild(visual);
    }

    public bool ContainsVisual(DrawingVisual visual)
    {
        return visuals.Contains(visual);
    }

    public bool HasVisuals
    {
        get { return visuals.Count > 0; }
    }

    public void RemoveAllVisuals()
    {
        for (int i = 0; i < visuals.Count; i++)
        {
            base.RemoveVisualChild(visuals[i]);
            base.RemoveLogicalChild(visuals[i]);
        }

        visuals.Clear();
    }

    public void RemoveLastVisual()
    {
        if (visuals.Count > 0)
        {
            int index = visuals.Count - 1;

            base.RemoveVisualChild(visuals[index]);
            base.RemoveLogicalChild(visuals[index]);
            visuals.Remove(visuals[index]);
        }     
    }

    public void RemoveVisual(DrawingVisual visual)
    {
        base.RemoveVisualChild(visual);
        base.RemoveLogicalChild(visual);
        visuals.Remove(visual);            
    }
}

(我确实是从网上某处得到的,但我不记得前一段时间在哪里了。)

无论如何,该程序允许用户通过用鼠标中键拖动来平移显示在 上的图形Graphics_Canvas,这将不断(只要他们继续平移)触发如下所示:

            //get the data visual:
            DrawingVisual tempVisual = GetDataDrawingVisual();

            //first clear the current display data:
            myCanvas.RemoveVisual(dataVisual);

            //get the data visual:
            dataVisual = tempVisual;

            myCanvas.AddVisual(dataVisual);

所以我不断删除然后重新添加dataVisual.

当我查看内存使用时,我注意到的是,四处移动会导致内存使用增加,虽然它确实再次下降,但它并没有完全恢复到以前的水平。当显示屏上根本没有任何内容时,这一点更加明显,并且持续有效地重新添加任何内容的内存使用量可能会上升到数百 MB,并且在平移停止时再次下降。

作为信息,我应该补充一点,它GetDataDrawingVisual()返回 a Visual,在其上绘制 a RenderTargetBitmap,它本身不会保留在该方法之外。

我的问题是为什么这会导致内存使用量变化如此之大?

目前这更像是一个奇怪的麻烦,但我可以预见,如果可用内存一开始就受到更多限制,这可能是一个问题。

任何见解将不胜感激。

* 更新 (21/03/2013) *

通过对 的试验Graphics_Canvas,似乎以下方法对未释放的内存量产生了相当大的影响:

protected override Visual GetVisualChild(int index)
{
    return visuals[index];
}

如果我只是返回 anew DrawingVisual()作为测试,那么在重新绘制结束后,内存几乎可以恢复到原来的位置。

但是,删除这个方法只是意味着Canvas不会运行,我会得到一个错误。可能是.NET 在幕后某个地方引用了Visual从这个方法返回的内容,然后没有取消引用它?我该如何排序?(注意:我从未在我的代码中显式调用此方法,它是从其他地方调用的)。

4

1 回答 1

1

我认为您的内存使用量变化如此之大的原因是垃圾收集器没有立即启动。因此,当您拖动对象时,会增加内存使用量,直到它运行为止。

您可以通过执行以下操作强制进行垃圾收集:

GC.Collect();
GC.WaitForPendingFinalizers();

这样你就肯定知道了。

关于为什么你的记忆没有一路回溯:也许你保留了对一些视觉效果的引用,而那些没有被收集?也许程序其他部分的某些东西正在建立内存?

您可能有内存泄漏,您可以查看这篇关于WPF 性能和 .NET Framework Client Profile的文章

于 2013-03-20T12:40:05.930 回答