wpf 为什么BitmapImage在使用MemoryStream时会使用如此多的内存?

nqwrtyyt  于 2023-08-07  发布在  其他
关注(0)|答案(2)|浏览(241)

我需要使用内存流,因为我从数据库加载图像。当我使用文件流时,只是为了比较,应用程序的占用空间与未压缩图像的1倍大小一致。但是如果我使用内存流,内存使用量更像是3倍。我使用了200MB的PNG图像(4张图像),应用程序占用了1GB的RAM。
有没有办法减少内存使用?

private BitmapImage readfromdsk(string s)
        {

            var photo2f = File.Open(s, FileMode.Open, FileAccess.Read);

            byte[] b = null;
            photo2f.Read(b=new byte[photo2f.Length], 0, (int)photo2f.Length);

            var bitmapImage = new BitmapImage();

            using (MemoryStream ms = new MemoryStream(b))
            {

                bitmapImage.BeginInit();
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.StreamSource = ms;   //// lot of memory allocated on this line
                bitmapImage.EndInit();
            }

            b = null;
            photo2f.Dispose();

            return bitmapImage;
        }

字符串

pzfprimi

pzfprimi1#

这里发生的是BitmapImage正在创建它自己拥有和管理的像素的副本。
在文件流版本中,它可以以小块(例如,一次4kb)。因此,在这个例子中,它将结束使用(4kb +未压缩位图大小)内存。
在您的内存流版本中,您首先将整个文件读入内存。所以它最终是(文件大小+未压缩位图大小)。BitmapImage不直接使用字节数组。它仍然一次“流”一个块。
如果你想在阅读数据库时减少内存,你需要构建一个流类(实现System.IO.Stream),它每次从数据库读取一个块。
最后要考虑的事情:这可能是也可能不是一个问题。GC将恢复字节数组使用的内存,因此内存使用的增加只是暂时的。

643ylb08

643ylb082#

正如在
.NET Memory issues loading ~40 images, memory not reclaimed, potentially due to LOH fragmentation
一个MemoryStream似乎保留了一个对你在构造时传递的字节数组的引用,即使在它被释放之后。这是一个问题,因为BitmapImage也保留了对其StreamSource的引用,因此原始输入字节数组永远不会被释放。
为了避免这种情况,您可以使用一个额外的BufferedStream,它会在释放它的源流时释放对它的引用。

public BitmapSource LoadBitmap(MemoryStream memoryStream)
{
    using (var bufferedStream = new BufferedStream(memoryStream))
    {
        var bitmap = new BitmapImage();
        bitmap.BeginInit();
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.StreamSource = bufferedStream;
        bitmap.EndInit();
        bitmap.Freeze();
        return bitmap;
    }
}

public BitmapSource LoadBitmap(string path)
{
    var buffer = File.ReadAllBytes(path);

    using (var memoryStream = new MemoryStream(buffer))
    {
        return LoadBitmap(memoryStream);
    }
}

字符串

相关问题