Список C# dispose / close
Я настраиваю абонентскую службу для отправки отчетов различным людям в нашей компании по расписанию. Я планирую отправить отчеты по электронной почте, система отчетов, которую я использую, может экспортировать в виде потока 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 ответов:
Почему бы не создать класс 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); }
Можно создать список 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(); } } }
Зависит от того, используются ли потоки позже, когда создается вложение. Я предполагаю, что они есть, что означает, что вы захотите избавиться от потоков в конце.
Не забудьте попробовать-наконец-то это. В противном случае они не будут удалены, если произойдет исключение.
Я не вижу логики в закрытии потоков сразу после добавления их в список. Судя по предоставленному вами коду, ссылки на эти потоки используются в других местах. Если потоки закрыты, то какой толк от них?
Нет никакого вреда в том, чтобы сделать Flush()/Close(). Если вы хотите быть абсолютно уверены, то вы должны сделать, используя оператор:
using (Stream stream = ReportSource.ReportDocument.ExportToStream(PortableDocFormat)) { reports.Add(stream); stream.Flush(); //unsure }Таким образом, исключения не повлияют на ваш код.
Comments