Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MemoryStream, Cannot access a closed stream

With the sharpPDF library I generate a pdf memory stream, and I want to send it directly via email. But the line ms.Seek(.... gives an ObjectDisposedException;

Cannot access a closed Stream.

The pdf.CreatePDF method takes either an (output) fileName string, or an (out)Stream. But I guess it also closes the stream? I'm not used to work much with streams, so if you could please advise how it should be done?

The sharpPDF source code of the CreatePDF method can be found here:

http://www.java2s.com/Open-Source/CSharp/PDF/SharpPDF/sharpPDF/pdfDocument.cs.htm

Public Sub SendPDF()
   Dim pdf As New sharpPDF.pdfDocument("Title", "Author")

   '....Generate pdf content

   Dim ms As New IO.MemoryStream
   pdf.CreatePDF(ms)

   Dim email As New EmailService
   email.Send(ms)

End Sub

Public Class EmailService
   Public Sub Send(Byval ms as Stream)
        ms.Seek(0, IO.SeekOrigin.Begin)

        Dim atc As New Attachment(ms, "Report.pdf")
        mail.Attachments.Add(atc)

        '....set other email parameters

        client.SendAsync(mail, mail.Subject)
  End Sub 
End Class
like image 371
bretddog Avatar asked Nov 11 '11 22:11

bretddog


People also ask

Does MemoryStream need to be disposed?

You needn't call either Close or Dispose . MemoryStream doesn't hold any unmanaged resources, so the only resource to be reclaimed is memory.

What is the difference between Stream and MemoryStream?

You would use the FileStream to read/write a file but a MemoryStream to read/write in-memory data, such as a byte array decoded from a string. You would not use a Stream in and of itself, but rather use it for polymorphism, i.e. passing it to methods that can accept any implementation of Stream as an argument.

What is a MemoryStream?

MemoryStream encapsulates data stored as an unsigned byte array. The encapsulated data is directly accessible in memory. Memory streams can reduce the need for temporary buffers and files in an application. The current position of a stream is the position at which the next read or write operation takes place.

What does Cannot access a disposed object mean?

: 'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application.


1 Answers

One simple approach is to get the byte array out of the closed MemoryStream and create another one:

pdf.CreatePDF(ms)
ms = new MemoryStream(ms.ToArray())

Dim email As New EmailService
email.Send(ms)

Note that it's fine to call MemoryStream.ToArray on a closed / disposed instance of MemoryStream. It's even documented:

Note
This method works when the MemoryStream is closed.

like image 114
Jon Skeet Avatar answered Sep 21 '22 17:09

Jon Skeet