PdfGenerator EmailMessage EmailAttachment-无法访问关闭的流

时间:2018-10-23 17:07:56

标签: c# asp.net webforms kentico

尝试将System.ObjectDisposedException Cannot access a closed Stream附加并发送到System.IO.MemoryStream时,引发了错误消息EmailAttachment,错误消息EmailMessage。正在使用HtmlRenderer.PdfSharp生成附件。附加和发送是在using语句中完成的。

using (MemoryStream ms = new MemoryStream())
{
    var pdf = PdfGenerator.GeneratePdf("<html><body>foo</body></html>", PdfSharp.PageSize.Letter);
    // 2nd argument is to NOT close stream
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    // SiteContext.CurrentSiteName argument is just a site name required for Kentico CMS
    // true argument is send immediately
    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);    
}

如果我改为执行以下操作,则表示成功,只要我不尝试在ms.Dispose()块内进行try,就不会发生错误:

MemoryStream ms = new MemoryStream();
try
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception)
{
    ms.Dispose();
}

第二种方法的问题在于MemoryStream未被明确处理。 MemoryStream是否固有地被这种方法处理?如果将ms.Dispose(); 放在之后,则会出现相同的Cannot access a closed Stream。这是内存泄漏等待发生吗?如何处置MemoryStream而又不关闭流以允许电子邮件发送附件?

这是一个需要以某种方式等待SendEmail()实际执行其功能的问题吗?

感谢您提供的任何帮助。

3 个答案:

答案 0 :(得分:0)

  1. 我不明白为什么要将ms放在try块中,通常是为了清理变量,您可以使用finally块,无论是否有异常,它将始终执行。

    < / li>
  2. 如果使用catch(带有Exception的catch会捕获所有异常),则不会因为捕获它们而得到错误

您应该如何做:

MemoryStream ms = new MemoryStream();
try
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
ms.Dispose();
}

答案 1 :(得分:0)

我可以使用以下代码来找到解决方案。实际上,与sendImmediately的{​​{1}}参数有关的更多是Kentico CMS问题。通过将其设置为SendMail()(默认),我可以将流作为false附加,而在EmailAttachment语句中都没有System.ObjectDisposedException错误。

using

答案 2 :(得分:0)

好吧,您只需要关闭流即可从Kentico访问流,即:

using (MemoryStream ms = new MemoryStream())
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
    pdf.Save(ms, false);
}

然后您要做电子邮件部分:

        EmailMessage em = new EmailMessage();
        em.EmailFormat = EmailFormatEnum.Html;
        em.From = "no-reply@foo.com";
        em.Recipients = "foo.bar@baz.net";
        em.Subject = "Attachment Name";
        em.Body = "There is an attachment.";
        using (MemoryStream ms = new MemoryStream())
        {
           var attachment = new EmailAttachment(ms, "foo.pdf");
           em.Attachments.Add(attachment);
        }
        EmailSender.SendEmail(SiteContext.CurrentSiteName, em);