C# List<Stream> dispose/close

*爱你&永不变心* 提交于 2021-02-07 13:46:00

问题


I am setting up a subscription service to send reports to various people in our company on a schedule. I plan to email the reports, the reporting system I am using is able to export as PDF stream (rather than writing temp files). Most people will receive more than one report so I am trying to attach them all to one email doing something like

List<Stream> reports = new List<Stream>();
//looping code for each users set of reports
Stream stream = ReportSource.ReportDocument.ExportToStream(PortableDocFormat)
reports.Add(stream);
stream.Flush();  //unsure
stream.Close();  //unsure
//end looping code

SmtpClient smtpClient = new SmtpClient(host, port);
MailMessage message = new MailMessage(from, to, subject, body);

foreach (Stream report in reports)
{
    message.Attachments.Add(new Attachment(report, "application/pdf"));
}                
smtpClient.Send(message);

What I am unsure about is should I be flushing and closing the stream just after adding it to the list will this be ok? Or do I need to loop the List afterwards to flush and dispose? I am trying to avoid any memory leak that is possible.


回答1:


Why not create a StreamCollection class that implements IDisposable:

public class StreamCollection : Collection<Stream>, IDisposable { }

In the Dispose method of that class, you could loop through all of the streams and properly Close/Dispose of each stream. Then your code would look like:

using (var reports = new StreamCollection())
{
   //looping code for each users set of reports
   reports.Add(ReportSource.ReportDocument.ExportToStream(PortableDocFormat));
   //end looping codeSmtpClient 

   smtpClient = new SmtpClient(host, port);
   MailMessage message = new MailMessage(from, to, subject, body);

   foreach (Stream report in reports)
   {    
      message.Attachments.Add(new Attachment(report, "application/pdf"));
   }

   smtpClient.Send(message);
}



回答2:


You could create a DisposableList that you can wrap in a using statement:

public class DisposableList<T> : List<T>, IDisposable where T : IDisposable {

    // any constructors you need...

    public void Dispose() {
        foreach (T obj in this) {
            obj.Dispose();
        }
    }
}



回答3:


Depends on if the streams are used later on when the attachment is created. I assume they are which means you'll want to dispose the streams at the end.

Remember to try-finally this. Otherwise they wont be disposed if an exception occurs.




回答4:


I do not see the logic in closing the streams right after adding it to the list. Based on the code you have provided it appears the references to those streams are being used in other places. If the streams are closed then what good do they serve?




回答5:


There is no harm whatsoever in doing Flush()/Close(). If you want to be absolutely sure, then you should do a using statement:

using (Stream stream = ReportSource.ReportDocument.ExportToStream(PortableDocFormat))
{
    reports.Add(stream);
    stream.Flush();  //unsure
}

This way, exceptions will not affect your code.



来源:https://stackoverflow.com/questions/1848065/c-sharp-liststream-dispose-close

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!