我现在正在编写一个Windows应用商店应用阅读器,用于使用C#查看PDF文件。
目前,我正在尝试解决可能导致内存泄漏的问题。 在app中,有一种加密和解密PDF文件的方法,加密/解密方法是自定义方法,PDF文件的大小在1MB到120MB之间。
在加密和解密过程中,必须将文件作为字节数组读入内存,并处理字节以进行加密和解密。 从方法返回后,字节数组超出范围。但似乎因为它是一个大字节数组(> 85k),我认为它是在大对象堆(LOH)中声明的,并且在收集垃圾后,看起来LOH变得支离破碎。
在应用程序打开,查看和切换更多PDF文件后,内存使用率会越来越高,并且在某些时候会发生内存不足异常。
有没有办法解决大字节数组问题?或者有人遇到过这样的问题吗?
我找到了内存映射文件类,但它无法在Windows应用商店应用中使用。
我还尝试了大量字节数组(< 85k)并逐个处理文件,但在查看PDF之前加密和解密需要很长时间。
以下是代码段:
public static async Task CryptoFile(StorageFolder文件夹,字符串FileName,bool IsReaderFile)
{
...
...
byte[] fileContent = null;
buffer = await FileIO.ReadBufferAsync(file);
using (DataReader dataReader = DataReader.FromBuffer(buffer))
{
fileContent = new byte[dataReader.UnconsumedBufferLength];
dataReader.ReadBytes(fileContent);
}
if (fileContent == null)
CryptResult = false;
else if (fileContent.Length == 0)
CryptResult = false;
if (CryptResult)
{
//Encrypt/decrypt file
fileContent = await RecodeFile(fileContent, CryptKey, IsReaderFile);
//Delete the original file
file = await Folder.GetFileAsync(FileName);
await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
//Recreate file
file = await Folder.CreateFileAsync(FileName);
using (IRandomAccessStream fs = await file.OpenAsync(FileAccessMode.ReadWrite))
{
using (IOutputStream outStream = fs.GetOutputStreamAt(0))
{
using (DataWriter dataWriter = new DataWriter(outStream))
{
dataWriter.WriteBytes(fileContent);
await dataWriter.StoreAsync();
dataWriter.DetachStream();
}
await outStream.FlushAsync();
}
}
....
}
}
fileContent是用于读取整个文件内容的字节数组,当从方法返回时它将超出范围,我认为fileContent导致内存碎片,因为它的大小可能在LOH中声明。
答案 0 :(得分:0)
假设您的问题与LOH相关,您考虑将较小的阵列包装成LOH友好阵列替代品。如果您愿意将块大小限制为2的幂,则可以进一步优化该示例。然后div mod变为shift和bitmask。显然,如果需要,你可以实现所有的ICollection。
我之前使用过这种方法,性能合理。
public sealed class ArrayRope<T>
{
private readonly T[][] map;
private readonly int blockSize;
private readonly int noOfBlocks;
public ArrayRope(int blockSize, int noOfBlocks)
{
...
}
public T this[int index]
{
get
{
int ropeIndex = index / blockSize;
int offset = index % blockSize;
return map[ropeIndex][offset];
}
set
{
int ropeIndex = index / blockSize;
int offset = index % blockSize;
map[ropeIndex][offset] = value;
}
}
...
}