2015-11-06 15 views
8

Poniższy kod jest używany do zszyć istniejące pliki PDF [Tak na marginesie używamy TallComponents zrobić rzeczywisty szwy, w przypadku, gdy zastanawiasz się co PDFUtility jest]:Jak pozbyć się obiektu MemoryStream

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

Widoczna z kodem jest polecenie:

MemoryStream fileContentStream = new MemoryStream(content); 

strumień pamięci fileContentStream nie wychodzi umieszczony potencjalnie (wierzę) trzymając zasobach dłużej niż to jest konieczne.

Oczywistym rozwiązaniem byłoby zawinięcie tworzenia obiektu MemoryStream w blok using. Kod powinien wyglądać następująco:

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

Zastosowanie wykorzystaniem przekształcenia blokowego w powyższym kodu powoduje kod niepowodzenie w tej linii (ponieważ strumienie uprzednio usunięte)

docFinal.Write(stream); 

Jeden możliwym rozwiązaniem byłoby śledzenie wszystkich instancji MemoryStream i usuwanie ich po ich użyciu. Oto kod:

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 

Powyższy kod działa. Po prostu odkładam Dispose do czasu, aż dokument końcowy zostanie wypisany.

Jednak to nie wydaje się być "najlepszym" rozwiązaniem. Czy istnieje jakiś sposób, aby realizować przy użyciu bloków (a tym samym gwarantując obiekty są odpowiednio przygotowani?

+0

Czy istnieje jakaś metoda 'docFInal.Flush', którą można wywołać przed wyjściem z pętli? –

+0

Zobacz [MemoryStream musi być wyraźnie usunięty?] (Http://stackoverflow.com/questions/4195746/memorystream-must-be-explicitely-be-dposed). – MicroVirus

+1

I jeszcze jeden (wydaje się bardziej aktywny) http://stackoverflow.com/questions/234059/is-a-memory-leak-created-if-a-memorystream-in-net-is-not-notlosed – shurik

Odpowiedz

5

using bloki nie są o wiele bardziej niż cukier składniowej dla try-finally bloków.

W zależności od sposobu korzystania z użyciem bloku, skończyć się z dwóch rodzajów bloków try-wreszcie

Przypadek 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; 
    } 
} 

Sprawa druga:

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

Dzięki tej wiedzy możesz zmodyfikować trzecie rozwiązanie, aby użyć bloku finally, aby upewnić się, że twoje obiekty MemoryStream są zawsze czyszczone.

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 
} 
Powiązane problemy