将对象传递给其他函数

时间:2015-06-15 15:34:43

标签: c# smtp itextsharp memorystream

我的主要问题是如果我将对象传递给使用MemoryStream的函数如何清除内存流?请参阅下面的代码。

更详细: 我正在尝试使用iTextSharper动态创建PDF时发送多封电子邮件。我想确保我在这里没有对MemoryStream做错。我无法使用using语句,因为当我执行EmailPDF功能时,连接已关闭,如果我不为每个PDF创建使用新的MemoryStream,它将覆盖之前创建的。

我将pdf添加到附件中,然后将附件添加到列表中。然后我使用该列表将附件添加到mailmessage。然后我发送消息。

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

4 个答案:

答案 0 :(得分:2)

一个选项是在catch之后最后添加并使用Close()或Dispose()。当他们在MemoryStream上调用时,他们可以做两件事:

标记处置的对象,以便将来意外使用该对象将引发异常。 可能会释放对托管对象的引用,这可以使GC的工作更容易,具体取决于GC实现。 (在今天的GC算法上它没有什么区别,所以这是学术讨论的一个点,并没有显着的现实影响。)

MemoryStream没有任何非托管资源可供处理,因此您在技术上不必处置它。不处理MemoryStream的效果与删除对byte []的引用大致相同(GC将以相同的方式清除它们。)

我打电话给哪一个?是否有必要同时打电话? Stream的Dispose()方法直接委托给Close()方法2,因此两者完全相同。如果你愿意,你可以跳过它。毕竟GC会清理它。

答案 1 :(得分:2)

创建一个类

public class MyAttachment {
    MemoryStream output {get; set;}
    System.Net.Mail.Attachment {get; set;}
}

重写您的FillAttachmentList(lstFields);方法以提供列表&lt; MyAttachment&gt ;;

代替attachments.Clear();写:

foreach (MyAttachment attach in attachments)
{
    if ( attach.output != null) {
        attach.output.Close();
    }
}
attachments.Clear();

实际上你应该实现MyAttachmentCollection : IEnumerable<MyAttachment>, IDisposable

答案 2 :(得分:1)

在你的上下文中,就像@Stoyan所说的那样,如果你想要你可以强制GC使用GC.Collect()来强制移动流,那就不会有什么区别了。

答案 3 :(得分:1)

您的MemoryStream没有提及非托管资源,因此您可能不会关闭或处置它。搜索会找到解决此问题的other questions

但是,MailMessage及其所有组成部分都会实现IDisposable。如果您follow through the reference source,则会通过处置您的MailMessage来查看附件中的信息流。

因此,要成为一名优秀的公民,您应该在发送邮件后直接致电mm.Dispose(),或者在MailMessage声明中使用using