【问题标题】:Free completely memory of byte[]完全释放 byte[] 的内存
【发布时间】:2018-01-10 21:58:52
【问题描述】:

我正在创建一个流式应用程序,它使用以下代码从服务器连续性中获取字节:

while (true)
            {
                byte[] buffer = await _client.GetStreamOneCameraAsync();
                if (buffer.Length == 0) continue;
                SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer.AsBuffer(), BitmapPixelFormat.Gray8, 1280, 960);
                //buffer = null; if I put this here, it will solve the memory leak
                //GC.Collect();
                if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
                    softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
                {
                    softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
                }
                _imageSource = new SoftwareBitmapSource();
                await _imageSource.SetBitmapAsync(softwareBitmap);

                // Set the source of the Image control
                image_Preview.Source = _imageSource;

            }

所以我的问题是:是否足以清除 byte[] 占用的所有内存? 我的下一个任务是将该图像显示到 UI。那么也许它会导致内存泄漏?

更新: 谢谢你们的支持。我只是意识到,当我将该缓冲区转换为图像并将其显示到 UI 中而不是处理它时,我的内存泄漏问题就出现了。这不是由于字节[]

更新 2:我更新了全部代码。请帮我检查一下内存泄漏在哪里?

【问题讨论】:

  • 也许只有我一个人,但如果你的下一次迭代会覆盖buffer,我看不出有什么意义。我怀疑您正在尝试解决由// Do some stuff 而不是您的byte[] buffer 引起的问题。
  • 很少有需要显式调用GC.Collect() 的情况,我认为在循环中调用会比可能不取消分配字节数组产生更大的性能影响。当您在每次循环迭代时重新定义 buffer 时,让 GC 完成它的工作并为您管理堆。
  • 我偶尔会遇到快速连续分配多个大缓冲区的内存问题,这些问题已通过调用 GC.Collect() 解决 - 我认为问题与内存碎片有关,而不是内存不足- 看到这个link。将任何一次性对象(如 SoftwareBitmap)放在 using 语句中并将 GC-Collect() 调用移动到 while 循环的开头或结尾可能是合适的。
  • 占用的内存旧字节[]并未消失。我一直在跟踪 VS 2017 中的处理内存图表,发现它增长得非常快。所以我觉得这里有必要设置buffer = null。

标签: c# .net garbage-collection


【解决方案1】:

其实我认为在这里将buffer 设置为null 是没有意义的。
一旦你的循环重置,他的缓冲区无论如何都会被重新定义,并且旧的内存将被自动 GarbageCollector 清除。

如果您确实发现了内存泄漏,您可以尝试强制进行垃圾回收,但在这种情况下,没有必要这样做。 (尽管这可能取决于您的方法在// Do some stuff 之后如何进行。)

参考文献:

Whats so wrong about GC.Collect()?
When is it acceptable to call GC.Collect?

编辑:

我相信将 SoftwareBitmap 放在 using 子句中以保证资源被释放,应该可以解决您的内存泄漏问题。

using (SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer.AsBuffer(), BitmapPixelFormat.Gray8, 1280, 960);)
{
    buffer = null;
    GC.Collect();
    if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
        softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
    {
        softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    }
    _imageSource = new SoftwareBitmapSource();
    await _imageSource.SetBitmapAsync(softwareBitmap);

    // Set the source of the Image control
    image_Preview.Source = _imageSource;
}

【讨论】:

  • 所占用的内存旧字节[] 并未消失。我一直在跟踪 VS 2017 中的处理内存图表,发现它增长得非常快。所以我认为有必要在这里设置buffer = null
  • 我认为 Visual Studio 提供了查看内存部分用完的工具。你可以试试看吗?
  • 还没有。但是在我设置 buffer = null 之后它停止增加所以我认为我有一些内存泄漏
  • 这很奇怪。通常 C# 会覆盖缓冲区。
  • 我下面的一些代码,我将缓冲区转换为图像并显示它。也许它会导致内存泄漏
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
  • 2019-05-01
  • 1970-01-01
  • 2015-04-25
相关资源
最近更新 更多