我有一些代码可以在电子邮件中添加附件。我正在通过Attachment
类构造函数的Stream
超载添加它们。这样做的代码看起来像:
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();
}
}
但是,如果仍然有没有收集垃圾或其他内容的参考文献,但如果仍然有一个参考文献,则不会正确地将它们处置。有任何想法吗?
处理此操作的最简单方法就是在MailMessage
上调用Dispose()
。
MailMessage.Dispose
将自动处置所有附件,而这些附件又将关闭/ Dispose()
所有基础流。
//other processing
emailClient.Send(message);
message.Dispose(); // Or just wrap this entire block in a using statement
这已经由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);
}
已经有正确的回复(mailmessage.dispose),因此"如果仍然有参考,请正确处理它们...":
处置意志(也预期)在呼叫时释放资源,无论谁提及该对象。一种常见的方法之一是在对象中还具有内在标志,该旗帜实现了处置的处置,该标志将通过抛出"对象处置"例外。
。,如果您在使用它们之前将流处置,则可以(并且可能已经这样做)观察此行为。IE。在您的邮件案例中,您可以尝试在message.Attachments.Add(attach);
之后立即处置流,这很可能会导致Send
拨打电话中的"流处置"例外。
请注意,在处置后有一些对象,例如内存中有特殊定义的行为。IE。MemoryStream屏蔽除了Toarray/Lenght/GetBuffer以外的所有调用,因为该类的主要目的之一是为您提供流的字节数组。作为副作用MemoryStream
的Dispose
本质上只是设置标志来阻止其他呼叫(这很好,因为该类没有任何本机资源)。