简体   繁体   English

如何处置MemoryStream对象

[英]How to dispose of a MemoryStream object

The following code is used to stitch together existing PDFs [As an aside we are using TallComponents to do the actual stitching, in case you were wondering what PDFUtility is]: 以下代码用于拼接现有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();
}

The glaring problem with this code is this command: 这段代码的明显问题是这个命令:

MemoryStream fileContentStream = new MemoryStream(content);

The memory stream fileContentStream is not getting disposed, potentially (I believe) holding onto resoures longer than needed. 内存流fileContentStream没有被处理掉,可能(我相信)保持资源的时间超过了所需的时间。

The obvious solution would be to wrap the creation of the MemoryStream in a using block. 显而易见的解决方案是将MemoryStream的创建包装在using块中。 The code would then look like this: 代码将如下所示:

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();
}

The use of the using block in the above code causes the code to fail on this line (because the streams were previously disposed): 在上面的代码中使用using块导致代码在此行上失败(因为之前已经处理了流):

docFinal.Write(stream);

One possible solution would be to keep track of all the MemoryStream instances and dispose of them after they are done being used. 一种可能的解决方案是跟踪所有MemoryStream实例并完成它们之后将其丢弃。 This is the code for that: 这是代码:

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

The code above works. 上面的代码有效。 I am simply delaying the Dispose until after the the final document is written out. 我只是推迟Dispose直到最终文件被写出来之后。

However, this doesn't seem like the "best" solution. 但是,这似乎不是“最佳”解决方案。 Is there any way to implement using blocks (and thus guaranteeing the objects are properly disposed? 有没有办法实现使用块(从而保证对象被妥善处理?

using blocks are not much more than syntactic sugar for try-finally blocks. using块并不比try-finally块的语法糖多得多。

Depending on how the using block is used, you end up with two types of try-finally blocks. 根据使用块的使用方式,最终会得到两种类型的try-finally块。

Case 1: 情况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;
    }
}

Case two: 案例二:

// 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.
}

With this knowledge, you can modify your third solution to use a finally block to ensure that your MemoryStream objects are always cleaned up. 有了这些知识,您可以修改第三个解决方案以使用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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM