将对象传递给不同的函数后清除 MemoryStream
Clear MemoryStream after passing the objects to a different function
我的主要问题是,如果我将对象传递给使用 MemoryStream 的函数,我该如何清除内存流?请参阅下面的代码。
更详细:
我正在尝试发送多封电子邮件,同时使用 iTextSharper 即时创建 PDF。我想确保我没有对这里的 MemoryStream 做错什么。我不能使用 using 语句,因为当我执行我的 EmailPDF 函数时说连接已关闭,而且如果我不为每个 PDF 创建使用新的 MemoryStream,它会覆盖以前创建的。
我正在将 pdf 添加到附件中,然后将附件添加到列表中。然后我使用该列表将附件添加到邮件消息中。然后我发送消息。
private void EmailPDF(List<String> lstFields)
{
MailMessage mm = new MailMessage("fromemailaddress", "toemailaddress")
{
Subject = "Test Email",
IsBodyHtml = true,
Body = "Testing email"
};
SmtpClient smtp = new SmtpClient
{
Host = "xxx.xxx.xxx.xxx"
};
List<System.Net.Mail.Attachment> attachments = FillAttachmentList(lstFields);
foreach (System.Net.Mail.Attachment attach in attachments)
{
mm.Attachments.Add(attach);
}
smtp.Send(mm);
attachments.Clear();
}
private List<System.Net.Mail.Attachment> FillAttachmentList(List<String> lstFields)
{
List<System.Net.Mail.Attachment> attachments = new List<System.Net.Mail.Attachment>();
foreach (String strField in lstFields)
{
MemoryStream output = new MemoryStream();
Document doc = new Document(PageSize.LETTER, 25, 25, 25, 25);
try
{
String text = System.IO.File.ReadAllText(@"C:\PDFDirectory\" + strField + ".html");
StringReader html = new StringReader(text);
PdfWriter wri = PdfWriter.GetInstance(doc, output);
doc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(wri, doc, html);
wri.CloseStream = false;
doc.Close();
attachments.Add(new Attachment(output, strField + ".pdf"));
output.Position = 0;
}
catch (Exception ex)
{
}
}
return attachments;
}
一个选项是在 catch 之后添加 finally 并使用 Close() 或 Dispose()。当它们在 MemoryStream 上被调用时,它们会做两件事:
标记已处置的对象,以便将来意外使用该对象时会引发异常。
可能释放对托管对象的引用,这可以使 GC 的工作更容易一些,具体取决于 GC 实现。 (在今天的 GC 算法上,它没有真正的区别,所以这是一个学术讨论的观点,对现实世界没有重大影响。)
MemoryStream 没有任何非托管资源可供处置,因此从技术上讲您不必处置它。不处理 MemoryStream 的效果与删除对 byte[] 的引用大致相同(GC 将以相同的方式清理两者)。
我叫哪个?有必要同时调用吗?
流的 Dispose() 方法直接委托给 Close() 方法 2,因此两者做完全相同的事情。如果你愿意,你可以跳过它。毕竟GC会清理它。
创建 class
public class MyAttachment {
MemoryStream output {get; set;}
System.Net.Mail.Attachment {get; set;}
}
重写您的 FillAttachmentList(lstFields);
方法以提供 List;
而不是 attachments.Clear();
写:
foreach (MyAttachment attach in attachments)
{
if ( attach.output != null) {
attach.output.Close();
}
}
attachments.Clear();
事实上你应该实现一个MyAttachmentCollection : IEnumerable<MyAttachment>, IDisposable
.
在您的上下文中,就像@Stoyan 所说的那样,这没有太大区别,如果您愿意,可以使用 GC.Collect() 强制 GC 刷流。
您的 MemoryStream
没有引用非托管资源,因此您最好不要关闭或处置它。搜索会发现 other questions 解决了这一点。
但是,MailMessage
及其所有组成部分都实现了 IDisposable
。如果你 follow through the reference source 你会看到你的附件中的流将通过处理你的 MailMessage
.
来关闭
因此,要成为一个好公民,您应该在发送消息后直接调用 mm.Dispose()
,或者将您对 MailMessage
的使用包装在 using
语句中。
我的主要问题是,如果我将对象传递给使用 MemoryStream 的函数,我该如何清除内存流?请参阅下面的代码。
更详细: 我正在尝试发送多封电子邮件,同时使用 iTextSharper 即时创建 PDF。我想确保我没有对这里的 MemoryStream 做错什么。我不能使用 using 语句,因为当我执行我的 EmailPDF 函数时说连接已关闭,而且如果我不为每个 PDF 创建使用新的 MemoryStream,它会覆盖以前创建的。
我正在将 pdf 添加到附件中,然后将附件添加到列表中。然后我使用该列表将附件添加到邮件消息中。然后我发送消息。
private void EmailPDF(List<String> lstFields)
{
MailMessage mm = new MailMessage("fromemailaddress", "toemailaddress")
{
Subject = "Test Email",
IsBodyHtml = true,
Body = "Testing email"
};
SmtpClient smtp = new SmtpClient
{
Host = "xxx.xxx.xxx.xxx"
};
List<System.Net.Mail.Attachment> attachments = FillAttachmentList(lstFields);
foreach (System.Net.Mail.Attachment attach in attachments)
{
mm.Attachments.Add(attach);
}
smtp.Send(mm);
attachments.Clear();
}
private List<System.Net.Mail.Attachment> FillAttachmentList(List<String> lstFields)
{
List<System.Net.Mail.Attachment> attachments = new List<System.Net.Mail.Attachment>();
foreach (String strField in lstFields)
{
MemoryStream output = new MemoryStream();
Document doc = new Document(PageSize.LETTER, 25, 25, 25, 25);
try
{
String text = System.IO.File.ReadAllText(@"C:\PDFDirectory\" + strField + ".html");
StringReader html = new StringReader(text);
PdfWriter wri = PdfWriter.GetInstance(doc, output);
doc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(wri, doc, html);
wri.CloseStream = false;
doc.Close();
attachments.Add(new Attachment(output, strField + ".pdf"));
output.Position = 0;
}
catch (Exception ex)
{
}
}
return attachments;
}
一个选项是在 catch 之后添加 finally 并使用 Close() 或 Dispose()。当它们在 MemoryStream 上被调用时,它们会做两件事:
标记已处置的对象,以便将来意外使用该对象时会引发异常。 可能释放对托管对象的引用,这可以使 GC 的工作更容易一些,具体取决于 GC 实现。 (在今天的 GC 算法上,它没有真正的区别,所以这是一个学术讨论的观点,对现实世界没有重大影响。)
MemoryStream 没有任何非托管资源可供处置,因此从技术上讲您不必处置它。不处理 MemoryStream 的效果与删除对 byte[] 的引用大致相同(GC 将以相同的方式清理两者)。
我叫哪个?有必要同时调用吗? 流的 Dispose() 方法直接委托给 Close() 方法 2,因此两者做完全相同的事情。如果你愿意,你可以跳过它。毕竟GC会清理它。
创建 class
public class MyAttachment {
MemoryStream output {get; set;}
System.Net.Mail.Attachment {get; set;}
}
重写您的 FillAttachmentList(lstFields);
方法以提供 List
而不是 attachments.Clear();
写:
foreach (MyAttachment attach in attachments)
{
if ( attach.output != null) {
attach.output.Close();
}
}
attachments.Clear();
事实上你应该实现一个MyAttachmentCollection : IEnumerable<MyAttachment>, IDisposable
.
在您的上下文中,就像@Stoyan 所说的那样,这没有太大区别,如果您愿意,可以使用 GC.Collect() 强制 GC 刷流。
您的 MemoryStream
没有引用非托管资源,因此您最好不要关闭或处置它。搜索会发现 other questions 解决了这一点。
但是,MailMessage
及其所有组成部分都实现了 IDisposable
。如果你 follow through the reference source 你会看到你的附件中的流将通过处理你的 MailMessage
.
因此,要成为一个好公民,您应该在发送消息后直接调用 mm.Dispose()
,或者将您对 MailMessage
的使用包装在 using
语句中。