它的作用:对于每个EncryptedBase64PictureFile,读取内容,解密base64字符串并创建一个图片框。
问题出在哪里:疯狂内存使用!我猜每个循环后的一些数据都没有被正确删除。例如,输入大约100MB加密数据的100个循环(应生成大约100MB的图像文件)使用大约1.5 GB的内存!当我尝试解密更多的数据,大约150MB时,我得到OutOfMemory异常。 Visual Studio的内存分析报告称,“string fileContent = reader.ReadToEnd();” line负责80%的分配。
for each EncryptedBase64PictureFile {
Rijndael rijAlg = Rijndael.Create();
rijAlg.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
rijAlg.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
FileStream fsread = new FileStream(EncryptedBase64PictureFile, FileMode.Open, FileAccess.Read);
ICryptoTransform desdecrypt = rijAlg.CreateDecryptor();
CryptoStream cryptostreamDecr = new CryptoStream(fsread,desdecrypt, CryptoStreamMode.Read);
StreamReader reader = new StreamReader(cryptostreamDecr);
string fileContent= reader.ReadToEnd(); //this should be the memory eater
var ms = new MemoryStream(Convert.FromBase64String(fileContent));
PictureBox myPictureBox= new PictureBox();
myPictureBox.Image = Image.FromStream(ms);
ms.Close();
reader.Close();
cryptostreamDecr.Close();
fsread.Close();
}
所以问题是,有没有办法在每次循环后正确处理内存?或者其他问题是什么? 每个想法的Thanx!
编辑: 当然我试图处理()所有4个流,但结果是相同的......
ms.Dispose();
reader.Dispose();
cryptostreamDecr.Dispose();
fsread.Dispose();
编辑: 发现问题。它不是dispose(),而是从流中创建图片。删除图片后,内存使用量从1.5GB增加到20MB。
编辑: 图片大约是500kb的.jpg格式,大约700kb的base64加密格式。但我真的不知道,影像箱对象有多大。
编辑: 输入大约100MB的100个循环意味着每个循环大约需要1MB,100个循环总共100MB
答案 0 :(得分:1)
另一个答案:和它一起生活。
如下所示:您在看似32位应用程序的情况下使用100mb块。如果没有重用缓冲区,由于大对象堆和一般内存碎片,这将无法工作。
如下:内存在那里,只是没有足够大的块。这会导致分配错误。
没有真正的解决办法,除了64位,较大的地址空间处理问题。
有关此信息,请访问:
https://www.simple-talk.com/dotnet/.net-framework/large-object-heap-compaction-should-you-use-it/
现在有一个可能的解决方案,可以实现大对象堆的结合:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect(); // This can be omitted
LOH的选择很费劲,但是运行aruond的100mb区域并不完全是GC的推荐方案。不是32位。
答案 1 :(得分:0)
解密您的信息流时使用base 64转换。不要使用Convert.FromBase64String
,因为这需要所有数据都在内存中。
using (FileStream f64 = File.Open(fileout, FileMode.Open) ) // content is in base64
using (var cs=new CryptoStream(f64, new FromBase64Transform(), CryptoStreamMode.Read ) ) // transform passed to constructor
using(var fo =File.Open(filein +".orig", FileMode.Create))
{
cs.CopyTo(fo); // stream is accessed as if it was already decrypted
}
从相关答案中取得的代码示例 - Convert a VERY LARGE binary file into a Base64String incrementally