【问题标题】:How much impact does memory stream have on ram/memory c# wpf? [closed]内存流对 ram/memory c# wpf 有多大影响? [关闭]
【发布时间】:2018-03-20 16:13:09
【问题描述】:

我目前对我的应用很困惑 :( 。我的应用占用了太多内存..

基本上我的应用程序是一个 WPF 应用程序,它有 3-4 个窗口和几个页面,每个窗口/页面在需要时/根据需要打开/显示。每个窗口/页面都有几个 Image 控件来显示图像。到检索图像(从资源中),我正在使用以下功能:

public BitmapImage LoadImage(Uri uri, bool LoadOnMemory, int Pixel)
{
if (LoadOnMemory == true)
{
    System.Windows.Resources.StreamResourceInfo sri = Application.GetResourceStream(uri);
    System.IO.BinaryReader binReader = new System.IO.BinaryReader(sri.Stream);
    byte[] buffer = binReader.ReadBytes(sri.Stream.Length);
    using (MemoryStream memoryStream = new MemoryStream(buffer))
    {
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.Default;
        bi.CreateOptions = BitmapCreateOptions.None;
        bi.StreamSource = memoryStream;
        bi.DecodePixelWidth = Pixel;
        bi.EndInit();
        bi.Freeze();
        return bi;
    }
}
else
{
    BitmapImage bi = new BitmapImage();
    bi.BeginInit();
    bi.CacheOption = BitmapCacheOption.Default;
    bi.CreateOptions = BitmapCreateOptions.None;
    bi.UriSource = uri;
    bi.DecodePixelWidth = Pixel;
    bi.EndInit();
    bi.Freeze();
    return bi;
}
}

我有,可能总共有 20 张图像并加载每张图像,该函数称为将 Pixel 设置为 30(有时为 40)和 LoadOnMemory 设置为 True。我的启动窗口有 2 张图像和 1 张TextBlock,调用相同的函数来加载两个图像。

我的应用启动后,在 任务管理器 中,我发现即使是启动画面也只有 2-3 行代码来加载 MainWindow 占用了 105+ mb RAM。当我的MainWindow 加载时,RAM/Memory 的消耗达到 200+ mb。主窗口调用函数几次因为MainWindow 中有近 10 个图像。从那里开始,无论如何许多Pages 或Windows 在我打开任意数量的图像时,RAM 的消耗保持不变。由于某种原因,它不会超过 220+ mb。

我怀疑我的函数使用 MemoryStream ,这可能是造成如此巨大内存消耗的原因。

但后来我创建了一个没有代码隐藏的虚拟窗口,只是一个空白窗口并启动了我的应用程序......即使是空白窗口也会消耗 100+ mb 的内存!!

但虚拟窗口不是我关心的问题,我的 qs 是,例如,如果我的应用程序有 20 个图像并且每个图像都是使用该函数加载的(或者我应该说内存流),它对 ram 有多大影响? (虽然我可以看到它使用了将近 200+ mb)。我的函数不会在应用程序中导致任何延迟/性能问题,但我只需要知道该函数是否会导致如此巨大的内存消耗?

更新:很抱歉提供有关空白窗口的误导性信息

到目前为止,我是在 VS 中运行应用程序,所以内存的总消耗实际上是 Intellitrace(占用超过 30mb)空白窗口(15 -20 mb 最大....

最后一个问题,因为我也更新了代码,哪个更好?关于应用程序的性能和内存消耗的代码的第二部分(不使用memorystream)或第一部分(使用memoryStream)?

【问题讨论】:

  • 您看到的是#memoryleak,因为您从不处理流
  • 将处理流可能会在一定程度上解决问题?
  • 自己试试
  • 但是空白窗口是什么?它占用 100+ mb 的内存
  • 然后找出所有你使用了实现 IDisposible 的对象并且你没有调用 dispose 或者没有用 'using' 包装它的地方

标签: c# wpf memorystream


【解决方案1】:

当您可以直接从 StreamResourceInfo 的 Stream 中加载 BitmapImage 时,您当然不需要中间 MemoryStream:

private ImageSource LoadImage(Uri resourceUri, int pixelWidth)
{
    var resource = Application.GetResourceStream(resourceUri);
    var bitmap = new BitmapImage();

    using (var stream = resource.Stream)
    {
        bitmap.BeginInit();
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.StreamSource = stream;
        bitmap.DecodePixelWidth = pixelWidth;
        bitmap.EndInit();
        bitmap.Freeze();
    }

    return bitmap;
}

但是,您根本不需要使用 Stream,这显然更简单:

private ImageSource LoadImage(Uri resourceUri, int pixelWidth)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.UriSource = resourceUri;
    bitmap.DecodePixelWidth = pixelWidth;
    bitmap.EndInit();
    bitmap.Freeze();
    return bitmap;
}

【讨论】:

  • 你能告诉我你的解决方案对内存消耗和性能有多大影响吗?
  • 自己试试。我的猜测是两者应该非常相似。
  • 在我实现这个之前,我想知道的是,这仍然会和我当前的功能有同样的影响吗?
  • 试试吧。除非您遇到严重的性能问题,否则您应该使用最简单的方法。
  • @zackraiyan - 但你能解释一下它是如何帮助的 不处理一次性用品可能是主要原因。另一个可能是MemoryStream 中的byte [] 数组在默认情况下未压缩的large object heap 上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-16
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 2013-11-21
  • 1970-01-01
相关资源
最近更新 更多