C# 将对象传递给其他函数后清除MemoryStream

C# 将对象传递给其他函数后清除MemoryStream,c#,smtp,itextsharp,memorystream,C#,Smtp,Itextsharp,Memorystream,我的主要问题是,如果我将对象传递给正在使用MemoryStream的函数,那么如何清除MemoryStream?请参阅下面的代码 更详细地说: 我尝试在使用iTextSharper动态创建PDF时发送多封电子邮件。我想确保我没有对这里的MemoryStream做错事。我不能使用using语句,因为当我执行EmailPDF函数时,会显示连接已关闭,而且如果我没有为每个PDF创建使用新的MemoryStream,它会覆盖以前创建的MemoryStream 我将PDF添加到附件中,然后将附件添加到列表

我的主要问题是,如果我将对象传递给正在使用MemoryStream的函数,那么如何清除MemoryStream?请参阅下面的代码

更详细地说: 我尝试在使用iTextSharper动态创建PDF时发送多封电子邮件。我想确保我没有对这里的MemoryStream做错事。我不能使用using语句,因为当我执行EmailPDF函数时,会显示连接已关闭,而且如果我没有为每个PDF创建使用新的MemoryStream,它会覆盖以前创建的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;
    }
private void EmailPDF(列表字段)
{            
MailMessage mm=新邮件(“fromemailaddress”、“toemailaddress”)
{
Subject=“测试电子邮件”,
IsBodyHtml=true,
Body=“测试电子邮件”
};
SmtpClient smtp=新SmtpClient
{
Host=“xxx.xxx.xxx.xxx”
};
列表附件=FillAttachmentList(lstFields);
foreach(System.Net.Mail.Attachment在附件中附加)
{
mm.附件。添加(附加);
}
smtp.Send(mm);
附件.Clear();
}
私有列表FillAttachmentList(列表字段)
{
列表附件=新列表();
foreach(lstFields中的字符串strField)
{                
MemoryStream输出=新的MemoryStream();
文档文档=新文档(PageSize.LETTER,25,25,25,25);
尝试
{
String text=System.IO.File.ReadAllText(@“C:\PDFDirectory\”+strField+“.html”);
StringReader html=新的StringReader(文本);
PdfWriter wri=PdfWriter.GetInstance(文档,输出);
doc.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(wri、doc、html);
wri.CloseStream=false;
doc.Close();
附件。添加(新附件(输出,strField+“.pdf”);
输出位置=0;
}
捕获(例外情况除外)
{
}
}
归还附件;
}

一个选项是在catch之后添加finally,并使用Close()或Dispose()。当在MemoryStream中调用它们时,它们有两个作用:

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

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

我该叫哪一个?有必要两个都打电话吗?
streams的Dispose()方法直接委托给Close()方法2,因此两者的作用完全相同。如果你愿意,你可以跳过它。GC最终会清理它。

一个选项是在catch之后添加finally并使用Close()或Dispose()。当在MemoryStream中调用它们时,它们有两个作用:

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

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

我该叫哪一个?有必要两个都打电话吗? streams的Dispose()方法直接委托给Close()方法2,因此两者的作用完全相同。如果你愿意,你可以跳过它。GC最终会清理它。

创建一个类

public class MyAttachment {
    MemoryStream output {get; set;}
    System.Net.Mail.Attachment {get; set;}
}
重写
FillAttachmentList(lstFields)提供列表的方法

而不是
attachments.Clear()写入:

foreach (MyAttachment attach in attachments)
{
    if ( attach.output != null) {
        attach.output.Close();
    }
}
attachments.Clear();
事实上,您应该实现一个
MyAttachmentCollection:IEnumerable,IDisposable

创建一个类

public class MyAttachment {
    MemoryStream output {get; set;}
    System.Net.Mail.Attachment {get; set;}
}
重写
FillAttachmentList(lstFields)提供列表的方法

而不是
attachments.Clear()写入:

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

事实上,您应该在您的上下文中实现一个
MyAttachmentCollection:IEnumerable,IDisposable
,就像@Stoyan所说的,这没有多大区别,如果您想强制GC使用GC.Collect()刷流。

在您的上下文中,就像@Stoyan所说的,这没有多大区别,如果需要,可以使用GC.Collect()强制GC扫描流。

您的
MemoryStream
没有对非托管资源的引用,因此不关闭或处置它可能没问题。搜索将找到此点的地址

但是,
MailMessage
及其所有组件都实现了
IDisposable
。如果您看到附件中的流将通过处理
邮件消息关闭


因此,要成为一个好公民,您应该在发送消息后直接调用
mm.Dispose()
,或者使用
语句将您对
邮件消息的使用包装在
中。

您的
MemoryStream
没有对非托管资源的引用,因此您可能可以不关闭或处置它。A.