Список C # <Stream>удалить / закрыть - PullRequest
6 голосов
/ 04 декабря 2009

Я настраиваю службу подписки для отправки отчетов различным людям в нашей компании по расписанию. Я планирую отправлять отчеты по электронной почте, и система отчетов, которую я использую, может экспортировать в виде потока PDF (вместо записи временных файлов). Большинство людей получат более одного отчета, поэтому я пытаюсь прикрепить их к одному письму, делая что-то вроде

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

В чем я не уверен, так это в том, что я должен очищать и закрывать поток сразу после добавления его в список. Или мне нужно потом зациклить список для очистки и удаления? Я пытаюсь избежать любой возможной утечки памяти.

Ответы [ 5 ]

20 голосов
/ 04 декабря 2009

Почему бы не создать класс StreamCollection, который реализует IDisposable:

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

В методе Dispose этого класса вы можете перебрать все потоки и правильно закрыть / удалить каждый поток. Тогда ваш код будет выглядеть так:

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);
}
4 голосов
/ 04 декабря 2009

Вы можете создать DisposableList, который вы можете заключить в оператор using:

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

    // any constructors you need...

    public void Dispose() {
        foreach (T obj in this) {
            obj.Dispose();
        }
    }
}
1 голос
/ 04 декабря 2009

Я не вижу логики в закрытии потоков сразу после добавления его в список. Судя по предоставленному вами коду, ссылки на эти потоки используются в других местах. Если потоки закрыты, то что хорошего они служат?

1 голос
/ 04 декабря 2009

Зависит от того, используются ли потоки позже при создании вложения. Я предполагаю, что это означает, что вы захотите расположить потоки в конце.

Не забудьте попробовать, наконец, это. В противном случае они не будут утилизированы в случае возникновения исключения.

0 голосов
/ 04 декабря 2009

Нет никакого вреда при выполнении Flush () / Close (). Если вы хотите быть абсолютно уверенным, то вы должны сделать , используя выражение:

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

Таким образом, исключения не повлияют на ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...