简体   繁体   English

C#列表 <Stream> 配置/关闭

[英]C# List<Stream> dispose/close

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). 我打算通过电子邮件发送报告,我正在使用的报告系统能够导出为PDF流(而不是编写临时文件)。 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. 我试图避免任何可能的内存泄漏。

Why not create a StreamCollection class that implements IDisposable: 为什么不创建实现IDisposable的StreamCollection类:

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. 在该类的Dispose方法中,您可以循环遍历所有流并正确关闭/处理每个流。 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);
}

You could create a DisposableList that you can wrap in a using statement: 您可以创建一个可以在using语句中包装的DisposableList:

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

    // any constructors you need...

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

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. 否则,如果发生异常,它们将不会被处置。

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? 如果溪流关闭,那么它们有什么用处?

There is no harm whatsoever in doing Flush()/Close(). 在Flush()/ Close()中没有任何伤害。 If you want to be absolutely sure, then you should do a using statement: 如果你想绝对确定,那么你应该做一个using语句:

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

This way, exceptions will not affect your code. 这样,异常不会影响您的代码。

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

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