【问题标题】:Converting byte array to memory stream and bitmap causing high memory usage将字节数组转换为内存流和位图导致高内存使用
【发布时间】:2019-11-14 05:22:51
【问题描述】:

我有一个字节数组列表。而且,我正在使用它通过内存流生成位图图像。

在保存图像时,内存使用率非常高。在某些时候,它会导致内存不足异常。

我试图注释掉保存文件,看看是否会导致这个问题。或者,手动调用 GC。没有任何改变,仍然使用高内存。我最新的代码是这样的:

List<byte[]> byteArrayList = helper.GetArrayList(); // Gets approximately 10k items.

for (int i = 0; i < byteArrayList.Count; i++)
{
    using (MemoryStream ms = new MemoryStream(byteArrayList[i]))
    {
        using (Bitmap bm = new Bitmap(ms))
        {
            bm.Save(fileLocation);

            bm.Dispose();
        }

        ms.Dispose();
    }

    byteArrayList[i] = null;

    byteArrayList.Remove(byteArrayList[i]);
}

byteArrayList.Dispose();

我该如何解决这个问题?

【问题讨论】:

  • 请注意,如果 Dispose 已经在 using 语句中,则不需要显式调用。将列表元素设置为 null 是毫无意义的,我个人不会为 Remove 调用而烦恼。 (byteArrayList.Dispose() 甚至可以编译吗?)
  • 为什么要标记 WPF? Bitmap 是一个 WinForms 类。
  • 显然您的字节数组已经包含编码位图帧。为什么不直接打电话给File.WriteAllBytes
  • @YSFKBDY,提交队列版本作为答案。

标签: c# wpf memory-leaks out-of-memory heap-memory


【解决方案1】:

我测试了您的代码,发现系统无法在循环中收集您的垃圾。因此,如果您在循环中创建这么多位图,内存会增加到峰值水平(例如 2-3-4 gbs),直到垃圾收集器运行。但是当循环结束时,内存水平下降到正常为时已晚。因此,当我在 BackgroundWORKER 而不是主线程中测试您的代码时,GC 不会卡在循环中并按预期运行,它将字节数组转换为位图并保存它们而不会消耗任何内存。

【讨论】:

    【解决方案2】:

    如果您将辅助方法更改为返回 Queue&lt;T&gt;...

    Queue<byte[]> byteArrayQueue = helper.GetQueue(); // Gets approximately 10k items.
    
    while (byteArrayQueue.Any())
    {
        using (var ms = new MemoryStream(byteArrayQueue.Dequeue()))
        {
            using (var bm = new Bitmap(ms))
            {
                bm.Save(fileLocation);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多