我有一些代码可以为电子邮件添加附件。我是通过Stream
类构造函数的Attachment
重载添加它们的。执行此操作的代码如下所示:
List<UploadedDocument> docs = DataBroker.GetUploadedDocs(Convert.ToInt32(HttpContext.Current.Session["offer_id"].ToString()));
//no need to keep this in session
HttpContext.Current.Session["offer_id"] = null;
int counter = 1;
foreach (UploadedDocument doc in docs)
{
stream = new MemoryStream(doc.doc);
attach = new Attachment(stream, "Attachment-" + counter.ToString());
message.Attachments.Add(attach);
}
其中doc.doc
是字节数组。我想妥善处理每个附件和流,但是在发送消息之前我不能这样做,所以我在考虑将它们添加到List<Attachment>
和List<Stream>
然后迭代并呼吁处置。
这样的事情:
List<Attachment> attachments;
List<Stream> streams;
//...
foreach(UploadedDocument doc in docs)
{
stream = new MemoryStream(doc.doc);
streams.Add(stream);
attach = new Attachment(stream,"Name");
attachments.Add(attach);
message.Attachments.Add(attach);
}
//other processing
emailClient.Send(message);
if(attachments != null)
{
foreach(Attachment attachment in attachments)
{
attachment.Dispose();
}
}
if(streams != null)
{
foreach(MemoryStream myStream in streams)
{
myStream.Dispose();
}
}
但是有些东西告诉我,如果仍然有一个没有收集垃圾或其他东西的参考文件,它将不会正确处理它们。有什么想法吗?
答案 0 :(得分:5)
处理此问题的最简单方法是在Dispose()
上致电MailMessage
。
MailMessage.Dispose
将自动处理所有附件,这些附件将关闭/ Dispose()
所有基础流。
//other processing
emailClient.Send(message);
message.Dispose(); // Or just wrap this entire block in a using statement
答案 1 :(得分:3)
这已由MailMessage.Dispose方法实施:
protected virtual void Dispose(bool disposing)
{
if (disposing && !this.disposed)
{
this.disposed = true;
if (this.views != null)
{
this.views.Dispose();
}
if (this.attachments != null)
{
this.attachments.Dispose();
}
if (this.bodyView != null)
{
this.bodyView.Dispose();
}
}
}
将MailMessage的使用情况包装到using
语句中,MailMessage使用的所有资源将在您离开using
阻止后释放:
using(var message = new MailMessage(from, to))
{
foreach (UploadedDocument doc in docs)
{
stream = new MemoryStream(doc.doc);
attach = new Attachment(stream, "Attachment-" + counter.ToString());
message.Attachments.Add(attach);
}
emailClient.Send(message);
}
答案 2 :(得分:0)
已经有正确的回复方式(MailMessage.Dispose),所以“如果仍有引用,请正确处理它们”......:
处理意愿(预期也会)在呼叫时释放资源,而不管谁有对象的引用。一种常见的方法是在实现Dispose的对象中也有内部标志,它将通过抛出“Object Disposed”异常来阻止任何进一步的调用。
如果在完成使用之前处理流,则可以(并且可能已经执行过)观察此行为。即在您的邮件案例中,您可能会尝试在message.Attachments.Add(attach);
之后立即处理流,这很可能会在Send
来电期间导致“流处理”异常。
请注意,有一些像MemoryStream这样的对象在Dispose之后有特殊定义的行为。即MemoryStream会阻止除ToArray / Lenght / GetBuffer之外的所有调用,因为此类的一个主要目的是为您提供流的结果字节数组。副作用MemoryStream
的{{1}}实际上只是设置标志来阻止其他调用(这很好,因为这个类没有任何本机资源)。