Поток не был открыт для чтения - PullRequest
0 голосов
/ 05 марта 2020

Я загружаю файл PowerPoint из облака. Чтобы ограничить многократный вызов для загрузки файла, я кеширую его, используя MemoryCache. Приведенный ниже код работает нормально при первом запуске, но после первого запуска выдает исключение:

"Поток не был открыт для чтения."

Ниже приведен код, который я использую:

var cache = MemoryCache.Default;
var memoryStream = new MemoryStream();
if(cache.contains(key)) {
    memoryStream = (MemoryStream)cache.Get(key);
} else {
    var file = getFile();
    cache.Add(key, file);
    memoryStream = (MemoryStream)cache.Get(key);
}

using(memoryStream) {
    Open file and do manupulation then save the file in cloud.
}

Обновленный код:

var cache = MemoryCache.Default;
byte[] data = (byte[])cache.Get(key);
if(data == null)
{
    data_stream = getData(); // get memorystream
    cache.Add(key, data_stream.ToArray(), new CacheItemPolicy());
    data = (byte[])cache.Get(key);
}

using(Stream outputStream = new MemoryStream(decktemplate)) {
    Open file and do manupulation then save the file in cloud.
}

все еще появляется следующая ошибка: «Операция Arithmeti c вызвала переполнение.»

Ниже приведено дерево стека:

   at MS.Internal.IO.Zip.ZipIOExtraField.ParseRecord(BinaryReader reader, ZipIOZip64ExtraFieldUsage zip64extraFieldUsage, UInt16 expectedExtraFieldSize)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryFileHeader.ParseRecord(BinaryReader reader, Encoding encoding)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock.ParseRecord(BinaryReader reader, Int64 centralDirectoryOffset, Int32 centralDirectoryCount, Int64 expectedCentralDirectorySize)
   at MS.Internal.IO.Zip.ZipIOCentralDirectoryBlock.SeekableLoad(ZipIOBlockManager blockManager)
   at MS.Internal.IO.Zip.ZipIOBlockManager.get_CentralDirectoryBlock()
   at MS.Internal.IO.Zip.ZipArchive.GetFiles()
   at System.IO.Packaging.ZipPackage.ContentTypeHelper..ctor(ZipArchive zipArchive, IgnoredItemHelper ignoredItemHelper)
   at System.IO.Packaging.ZipPackage..ctor(Stream s, FileMode mode, FileAccess access, Boolean streaming)
   at System.IO.Packaging.Package.Open(Stream stream, FileMode packageMode, FileAccess packageAccess, Boolean streaming)
   at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.OpenCore(Stream stream, Boolean readWriteMode)
   at DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(Stream stream, Boolean isEditable, OpenSettings openSettings)
   at DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(Stream stream, Boolean isEditable)

1 Ответ

0 голосов
/ 05 марта 2020

Хранение MemoryStream как объекта в кеше - очень плохая идея, потому что несколько потоков могут обращаться к нему одновременно. Намного лучше хранить полезную нагрузку , например, byte[] или ArraySegment<byte>, и использовать ее для создания разных MemoryStream для каждого абонента. В противном случае вы будете постоянно спотыкаться о себе:

byte[] payload = (byte[])cache.Get(key);
if (payload is null)
{
    payload = GetFilePayload();
    cache.Add(key, payload);
}
using(var memoryStream = new MemoryStream(payload, writable: false))
{
    // ...
}
...