【问题标题】:Workaround for memory leak when using WriteableBitmap.AddDirtyRect()使用 WriteableBitmap.AddDirtyRect() 时内存泄漏的解决方法
【发布时间】:2014-07-25 16:49:45
【问题描述】:

当直接写入后台缓冲区并在单个锁定/解锁中多次使用 AddDirtyRect 函数时,WriteableBitmaps 似乎存在内存泄漏。矩形需要在位图中定义不同的区域。当您尝试丢弃 WriteableBitmap 时,内存将会泄漏。

您可以通过将以下代码插入新的 WPF 应用程序来重新创建它。当应用程序启动时,调整窗口大小以创建新的 WriteableBitmaps 并观察内存增加。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Image m = new Image();
        m.Stretch = Stretch.Fill;
        this.Content = m;

        this.SizeChanged += OnSizeChanged;
    }

    private void OnSizeChanged(object sender, SizeChangedEventArgs args)
    {
        WriteableBitmap bm = new WriteableBitmap((int)args.NewSize.Width, (int)args.NewSize.Height, 96, 96, PixelFormats.Bgra32, null);

        bm.Lock();
        bm.AddDirtyRect(new Int32Rect(1, 1, 1, 1));
        bm.AddDirtyRect(new Int32Rect(2, 2, 1, 1));
        bm.Unlock();

        ((Image)this.Content).Source = bm;
    }
}

我们需要能够丢弃位图,因此保留相同的位图并重复使用它不是一种选择。我们也不能直接写入后台缓冲区,而是使用 WritableBitmap.WritePixels(),但它速度较慢,而且速度是个问题。

更新: 我已经测试了 WritePixels 方法,它仍然泄漏。这可能是在不同区域过快调用过多写入的问题。

【问题讨论】:

    标签: c# wpf memory-leaks


    【解决方案1】:

    我们已就此问题与 Microsoft 联系,这似乎是支持 WPF 的底层 c++ 库存在问题。我们没有得到关于何时(或是否)修复的承诺,但它仍然是 .NET 4.5.1 的一个错误。

    目前我们发现只有两种方法可以解决此问题,而且它们是相互排斥的。您可以:

    从不弄脏位图的任何子区域,只​​弄脏整个位图

    这种方法的问题在于性能。您可以尝试通过缩小位图来解决此问题,但可能在很多情况下这是不可能的。

    永远不要丢弃您的位图

    如果您要弄脏位图的多个子部分,那么您必须确保它永远不会被垃圾回收,除非您即将关闭应用程序。这会带来很多问题,因为您必须确保第一次创建位图时足够大。如果允许用户调整窗口大小,那么您必须使其适合整个桌面,但即使这样也是有问题的,因为用户可以更改他们的桌面分辨率或添加/删除显示器,这意味着您要么必须泄漏内存,要么没有足够的位图来覆盖整个可能的窗口大小。

    希望 Microsoft 将来会针对此问题发布修复程序,但同时要非常小心 WriteableBitmap,因为它很容易泄漏内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      • 2013-04-01
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 2013-09-02
      相关资源
      最近更新 更多