【问题标题】:WriteableBitmap Copy memory leakWriteableBitmap 复制内存泄漏
【发布时间】:2018-10-20 19:51:25
【问题描述】:

我正在研究WriteableBitmaps,我有一个方法:

  1. WriteableBitmap从参数复制到方法外的变量
  2. 适用于第一个位图
  3. 将复制的位图添加到UndoStack

此方法的重点是在位图上进行更改,然后在更改之前添加到撤消堆栈位图。

如果经常调用此方法,则会导致OutOfMemoryException

变量

private WriteableBitmap _oldBitmap;
private Image _oldImage;

方法

public Layer ExecuteTool(Layer layer, Coordinates startingCoords, Color color,int toolSize, ToolType tool)
{
    if (toolSize < 1) return null;
    Layer cLayer = layer;

    _oldBitmap = new WriteableBitmap(layer.LayerBitmap);
    _oldImage = layer.LayerImage;
    _oldImage.Source = _oldBitmap;

    switch (tool)
    {
        case ToolType.Pen:
            cLayer.LayerBitmap = DrawPixel(cLayer.LayerBitmap, startingCoords, toolSize,color);
            break;
        case ToolType.Bucket:
            cLayer.LayerBitmap = FloodFill(cLayer.LayerBitmap, startingCoords, color);
            break;
        case ToolType.Line:
            if (_toolIsExecuting == false)
            {
                LineAsync(cLayer, startingCoords, color, toolSize);
            }
            break;
        case ToolType.Circle:
            if(_toolIsExecuting == false)
            {
                CircleAsync(cLayer, startingCoords, color);
            }
            break;
        case ToolType.Rectangle:
            if(_toolIsExecuting == false)
            {
                RectangleAsync(cLayer, startingCoords, color);
            }
            break;              
        case ToolType.Earser:
            cLayer.LayerBitmap = DrawPixel(cLayer.LayerBitmap, startingCoords, toolSize, Colors.Transparent);
            break;
        case ToolType.Lighten:
            if(Mouse.LeftButton == MouseButtonState.Pressed)
            {
                cLayer.LayerBitmap = Lighten(cLayer.LayerBitmap, startingCoords);
            }
            else if(Mouse.RightButton == MouseButtonState.Pressed)
            {
                cLayer.LayerBitmap = Darken(cLayer.LayerBitmap, startingCoords);
            }
            break;
        default:
            break;
    }
    if (tool != ToolType.ColorPicker)
    {
        UndoManager.RecordChanges("ActiveLayer", new Layer(_oldBitmap, _oldImage), cLayer, string.Format("{0} Tool.", tool.ToString()));
    }

    return cLayer;
}

附言。不复制位图就不行

【问题讨论】:

  • 那么,为什么会出现内存泄漏?似乎您的代码按设计工作。您可能需要考虑不同的架构,例如存储初始图像和一系列增量修改的架构,它们通过从图像的最后一个完整版本缓存在撤消流中时重做来实现“撤消”。或者,当您保存的撤消步骤超过 10 个时,您可以通过序列化将项目从“撤消”流移动到磁盘上。

标签: c# wpf memory-leaks writeablebitmap


【解决方案1】:

众所周知,位图的尺寸很大。您不断将旧状态添加到撤消堆栈,从而阻止 GC 清理它们。这正是您不应该对图像等批量数据执行的操作。

我想你只是不小心做了一个例子,说明什么不能在那里做:)

解决办法:

停止保留大量未使用的图像!对撤消堆栈大小设置一些合理的限制。或者以不需要 MiB 的内存的方式解决这个问题。

要特别记住的一件事是内存中的图像是完全未压缩的。压缩仅适用于磁盘上的图像或通过网络传输的图像。为了显示或处理图像,必须撤消每个压缩步骤。它们占用的空间等于高度 X 宽度 X 颜色深度,就像未压缩的位图图像一样。

【讨论】:

    猜你喜欢
    • 2013-01-20
    • 2013-08-23
    • 2011-07-31
    • 2020-06-03
    • 1970-01-01
    • 2011-05-25
    • 2014-08-07
    • 2012-01-12
    相关资源
    最近更新 更多