如何处理MemoryStream对象

本文关键字:MemoryStream 对象 处理 何处理 | 更新日期: 2023-09-27 18:20:52

以下代码用于将现有PDF缝合在一起[顺便说一句,我们使用TallComponents进行实际缝合,以防您想知道PDFUtility是什么]:

PDFUtility.Document docFinal = new PDFUtility.Document();
PDFUtility.Document docToAdd = null;
byte[] combinedFile;
foreach (byte[] content in fileContents)
{
    MemoryStream fileContentStream = new MemoryStream(content);
    docToAdd = new PDFUtility.Document(fileContentStream);
    docFinal.Pages.AddRange(docToAdd.Pages.CloneToArray());
}
using (MemoryStream stream = new MemoryStream())
{
    docFinal.Write(stream);
    combinedFile = stream.ToArray();
}

这个代码的明显问题是这个命令:

MemoryStream fileContentStream = new MemoryStream(content);

内存流fileContentStream没有被处理,可能(我相信)占用资源的时间超过了需要的时间。

显而易见的解决方案是将MemoryStream的创建封装在using块中。代码看起来是这样的:

PDFUtility.Document docFinal = new PDFUtility.Document();
PDFUtility.Document docToAdd = null;
byte[] combinedFile;
foreach (byte[] content in fileContents)
{
    using (MemoryStream stream = new MemoryStream())
    {
        MemoryStream fileContentStream = new MemoryStream(content);
        docToAdd = new PDFUtility.Document(fileContentStream);
        docFinal.Pages.AddRange(docToAdd.Pages.CloneToArray());
    }
}
using (MemoryStream stream = new MemoryStream())
{
    docFinal.Write(stream);
    combinedFile = stream.ToArray();
}

使用上述代码中的using块会导致代码在这一行失败(因为流之前已被处理):

docFinal.Write(stream);

一种可能的解决方案是跟踪所有MemoryStream实例,并在使用完毕后将其处理掉。这是它的代码:

PDFUtility.Document docFinal = new PDFUtility.Document();
PDFUtility.Document docToAdd = byte[] combinedFile;
List<MemoryStream> streams = new List<MemoryStream>();
foreach (byte[] content in fileContents)
{
    MemoryStream fileContentStream = new MemoryStream(content);
    streams.Add(fileContentStream); //EACH INSTANCE OF A STREAM IS TRACKED
    docToAdd = new PDFUtility.Document(fileContentStream);
    docFinal.Pages.AddRange(docToAdd.Pages.CloneToArray());
}
using (MemoryStream stream = new MemoryStream())
{
    docFinal.Write(stream);
    combinedFile = stream.ToArray();
}
streams.ForEach(s => s.Dispose()); //DISPOSE OF ALL STREAMS HERE

上面的代码有效。我只是将Dispose延迟到最终文档写出之后。

然而,这似乎不是"最佳"解决方案。有没有任何方法可以使用块来实现(从而保证对象得到正确处理?

如何处理MemoryStream对象

using块对于try-finally块来说只不过是语法糖。

根据using块的使用方式,您最终会得到两种类型的try-filly块。

案例1:

// This code ...
using( var thing = new Thing() ) {
    thing.DoOperation();
}
// ... turns into this scoped try-finally:
{
    var thing = new Thing();
    try {
        thing.DoOperation();
    }
    finally {
        thing.Dispose();
        thing = null;
    }
}

案例二:

// This code ...
var thing = new Thing();
using( thing ) {
    thing.DoOperation();
}
// ... turns into this code
var thing = new Thing();
try {
    thing.DoOperation();
}
finally {
    thing.Dispose();
    // Note the lack of a null assignment.
}

有了这些知识,您可以修改第三个解决方案,使其使用finally块,以确保始终清理MemoryStream对象。

PDFUtility.Document docFinal = new PDFUtility.Document();
PDFUtility.Document docToAdd = byte[] combinedFile;
List<MemoryStream> streams = new List<MemoryStream>();
try 
{
    foreach (byte[] content in fileContents)
    {
        MemoryStream fileContentStream = new MemoryStream(content);
        streams.Add(fileContentStream); //EACH INSTANCE OF A STREAM IS TRACKED
        docToAdd = new PDFUtility.Document(fileContentStream);
        docFinal.Pages.AddRange(docToAdd.Pages.CloneToArray());
    }
    using (MemoryStream stream = new MemoryStream())
    {
        docFinal.Write(stream);
        combinedFile = stream.ToArray();
    }
}
finally 
{
    streams.ForEach(s => s.Dispose()); //DISPOSE OF ALL STREAMS HERE
}