如何处置 MemoryStream 对象
How to dispose of a MemoryStream object
以下代码用于将现有的 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 延迟到最终文档写出之后。
但是,这似乎不像 "best" 解决方案。有什么方法可以实现 using 块(从而保证对象被正确处理?
using
块只不过是 try-finally
块的语法糖。
根据 using 块的使用方式,您最终会得到两种类型的 try-finally 块。
案例 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
}
以下代码用于将现有的 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 延迟到最终文档写出之后。
但是,这似乎不像 "best" 解决方案。有什么方法可以实现 using 块(从而保证对象被正确处理?
using
块只不过是 try-finally
块的语法糖。
根据 using 块的使用方式,您最终会得到两种类型的 try-finally 块。
案例 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
}