2013-06-27 6 views
2

Теперь я пишу приложение для чтения приложений Windows, которое используется для просмотра файлов PDF с использованием C#.Большой массив байтов в приложении Windows Store

На данный момент я пытаюсь решить проблему, которая может вызвать утечку памяти. В приложении существует способ шифрования и дешифрования файлов PDF, метод шифрования/дешифрования является обычным методом, а размер файлов PDF составляет от 1 МБ до 120 МБ.

В процессе шифрования и дешифрования файл должен быть считан в память как массив байтов и обрабатывает байты для шифрования и дешифрования. После возврата из метода массив байтов выходит за пределы области видимости. Но кажется, что, поскольку это большой массив байтов (> 85k), я думал, что он объявлен в большой куче объекта (LOH), и после сбора мусора, похоже, что LOH становится фрагментированным.

И после того, как приложение открывается, просматривает и переключает больше файлов PDF, использование памяти становится все выше и в некоторых случаях происходит исключение из памяти.

Есть ли способ решить проблему с большим байтом? Или кто-нибудь сталкивается с такой проблемой?

Я нашел класс Memory Mapped Files, но он не может быть использован в приложении Windows Store.

Я также пробовал с блоком байтового массива (< 85k) и обрабатывал часть файла по частям, но для просмотра и дешифрования требуется слишком много времени для шифрования и дешифрования.

Ниже приведен фрагмент кода:
общественности статической асинхронной 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

Вы уверены, что нет корней, которые сохраняют вашу память высокой? Что вы делаете с массивом 'byte', как только закончите дешифрование? Можете ли вы дать нам какой-то код или, по крайней мере, поток процесса о том, как все это происходит? –

+0

Привет, Саймон, я опубликовал фрагмент кода ниже. –

ответ

0

Предполагая, что ваша проблема связана с LOH, вы считали, что упаковка меньших массивов в альтернативный массив LOH замените. Вы можете оптимизировать этот пример дальше, если вы хотите ограничить размеры блоков до двух. Затем div mod становится смещением и битовой маской. Очевидно, что вы можете реализовать все материалы 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; 
     } 
    } 

    ... 
}