2016-08-19 88 views
1

我不能在循环内使用using,因为那样我将无法发送电子邮件,因为cannot access a closed stream如何关闭在循环内创建的多个MemoryStream?

我不能using(MemoryStream memoryStream = new MemoryStream()){the rest of the codes},因为那么只有第一个excel将有数据,其余的将是空的,文件大小为64 B.我已经验证所有excel在通过电子邮件发送之前都有数据。

foreach (workbook excel in workbooks) 
{ 
    MemoryStream memoryStream = new MemoryStream(); 
    excel.hssfWorkBook.Write(memoryStream); 
    memoryStream.Position = 0; 
    mailMessage.Attachments.Add(new Attachment(memoryStream, excel.fileName, "application/vnd.ms-excel")); 
} 
smtpClient.Send(mailMessage); 
+1

处置内存流只会停止以后的读/写(你*不需要 - 你希望电子邮件库从流中读取)。处理流不会导致内存更快地被清理。据我所见,你的代码是正确的。但是,您可以在创建它们时将这些流添加到列表中,然后在发送后按照您的意愿处理每个流。请参阅[this](http://stackoverflow.com/a/234257/563532)以获取更多信息 – Rob

+2

我不会为此付出汗水。 MemoryStream实际上并没有任何非托管资源可供处理,所以让GC在不关闭或处置的情况下处理它就没有问题。请注意,尽管这是IDisposables最佳实践的例外。 –

+0

因为如上所述它没有非托管资源,所以MemoryStream不是真正的问题。但是,如果您确实有其他流,则只需在发送MailMessage对象后处理即可。它应该处置所有附件及其基础流。 –

回答

2

没有必要关闭这个内存流。

你只需要确保你的mailMessage正确处置。一旦它被处置,所有的附件也被处置,因此它们的Streams。看

MailMessagesource code here和搜索Dispose()实现:

public void Dispose() 
{ 
    Dispose(true); 
} 

protected virtual void Dispose(bool disposing) 
{ 
    if (disposing && !disposed) 
    { 
     disposed = true; 

     if(views != null){ 
      views.Dispose(); 
     } 
     if(attachments != null){ 
      attachments.Dispose(); 
     } 
     if(bodyView != null){ 
      bodyView.Dispose(); 
     } 
    } 
} 

要处置您的MAILMESSAGE,只需使用using像这样简单的例子:

using (var mailMessage = new MailMessage()) 
{ 
    using (var smtpClient = new SmtpClient()) 
    { 
     foreach (workbook excel in workbooks) 
     { 
      MemoryStream memoryStream = new MemoryStream(); 
      excel.hssfWorkBook.Write(memoryStream); 
      memoryStream.Position = 0; 
      mailMessage.Attachments.Add(new Attachment(memoryStream, excel.fileName, "application/vnd.ms-excel")); 
     } 
     smtpClient.Send(mailMessage); 
    } 
}