C#-在发送到电子邮件系统时附加FileStream.ObjectDisposedException

C#-在发送到电子邮件系统时附加FileStream.ObjectDisposedException,c#,C#,你好 我正在尝试将filestream文件附加到电子邮件发送附件。情况是,我需要使用FileStream创建一个文件,然后将其附加到我的电子邮件中 到目前为止,我的示例代码如下: 要创建文件,请执行以下操作: public FileStream CreateFileStream(){ using (var ms = new MemoryStream()) { var writer = new StreamWriter(ms); writer.WriteLine(

你好

我正在尝试将filestream文件附加到电子邮件发送附件。情况是,我需要使用
FileStream
创建一个文件,然后将其附加到我的电子邮件中

到目前为止,我的示例代码如下:

要创建文件,请执行以下操作:

public FileStream CreateFileStream(){
    using (var ms = new MemoryStream())
    {
    var writer = new StreamWriter(ms);

    writer.WriteLine("file content blah blah blahh");
    writer.Flush();

    //You have to rewind the MemoryStream before copying
    ms.Seek(0, SeekOrigin.Begin);

       using (var fs = new FileStream("Filename.txt", FileMode.Create))
       {
          ms.CopyTo(fs);
          return fs;
       }
    }
}
这是我发送电子邮件的示例代码

// attachment
var fileStreamFile = dto.FileStreamFile;

var contentType = new ContentType(MediaTypeNames.Text.Plain);
var attach = new Attachment(dto.FileStreamFile, contentType);
attach.ContentDisposition.FileName = "File.txt";

mail.Attachments.Add(attach);
...
// code for sending here
...
dto.FileStreamFile.Dispose(); // for disposing File Stream
fileStreamFile
不是null,但它会抛出一个错误,该错误表示

Handle='dto.FileStreamFile.Handle'引发了类型为'System.ObjectDisposedException'的异常。

当我注释掉附加代码时,电子邮件的发送仍然可以正常工作。当我包含用于附加
FileStream的代码时,电子邮件发送失败

需要帮忙吗?提前感谢您

您的代码

using (var fs = new FileStream("Filename.txt", FileMode.Create))
{
    ms.CopyTo(fs);
    return fs; // you are returning here
} // hang on, this is a using statement which will dispose fs!
将转化为这一点

FileStream fileStream = new FileStream("Filename.txt", FileMode.Create);
try
{
   return fileStream;
}
finally
{
   if (fileStream != null)
   {
      ((IDisposable)fileStream).Dispose();
   }
}
需要注意的是,如果在
try finally
return
,它将返回值存储在局部变量中,以在
finally
之后返回。看起来像这样

FileStream fileStream = new FileStream("Filename.txt", FileMode.Create);
try
{
   temp = fileStream;
}
finally
{
   if (fileStream != null)
   {
      ((IDisposable)fileStream).Dispose();
   }
}

return temp;
using (var stream = new MemoryStream())
   using (var writer = new StreamWriter(stream)) // using UTF-8 encoding by default
      using (var mailClient = new SmtpClient("localhost", 25))
         using (var message = new MailMessage("me@example.com", "you@example.com", "Just testing", "See attachment..."))
         {
            writer.WriteLine("file content blah blah blahh");
            writer.Flush();
            stream.Position = 0; // read from the start of what was written

            message.Attachments.Add(new Attachment(stream, "filename.csv", "text/csv"));

            mailClient.Send(message);
         }
我们可以看看IL,看看发生了什么

IL_0000: ldstr "someFile"
IL_0005: ldc.i4.2
IL_0006: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string, valuetype[mscorlib]System.IO.FileMode)
// stloc.0 Pops the current value from the top of the evaluation stack and stores it in the 
// local variable list at a specified index. This is your fs reference
IL_000b: stloc.0 
   .try
{
   // ldloc.0 Loads the local variable at a specific index onto the evaluation stack.
   // This is your fs reference
   IL_000c: ldloc.0
   // stloc.1 Pops the current value from the top of the evaluation stack and stores it in 
   // the local variable list at a specified index. This is your fs reference
   IL_000d: stloc.1
   IL_000e: leave.s IL_001a
} // end .try
finally
{
   IL_0010: ldloc.0
   IL_0011: brfalse.s IL_0019     
   IL_0013: ldloc.0
   // oh no we just Disposed fs!!!
   IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()
   IL_0019: endfinally
} // end handler

// ldloc.1 Loads the local variable at a specific index onto the evaluation stack.
// This is your fs reference
IL_001a: ldloc.1
//ret Returns from the current method, pushing a return value (if present) from 
//the callee's evaluation stack onto the caller's evaluation stack.
IL_001b: ret
简而言之,不要使用
语句从
返回
IDisposable
引用,因为它将被释放

您需要创建
文件流
(不使用
)并
在另一个上下文中处置它,或者重构代码

更新

但我的电子邮件发送不工作后,我把一个使用声明 用流覆盖电子邮件的发送

你可能把事情搞得太复杂了,试试这样吧

FileStream fileStream = new FileStream("Filename.txt", FileMode.Create);
try
{
   temp = fileStream;
}
finally
{
   if (fileStream != null)
   {
      ((IDisposable)fileStream).Dispose();
   }
}

return temp;
using (var stream = new MemoryStream())
   using (var writer = new StreamWriter(stream)) // using UTF-8 encoding by default
      using (var mailClient = new SmtpClient("localhost", 25))
         using (var message = new MailMessage("me@example.com", "you@example.com", "Just testing", "See attachment..."))
         {
            writer.WriteLine("file content blah blah blahh");
            writer.Flush();
            stream.Position = 0; // read from the start of what was written

            message.Attachments.Add(new Attachment(stream, "filename.csv", "text/csv"));

            mailClient.Send(message);
         }

谢谢你的小费,先生。我已经重构了我的代码。我还有一个问题,所以我已经删除了using
using
语句,我可以在使用它的其他类中处理流吗?就像在发送电子邮件之后,我想处理它。可以使用类似于
dto.FileStreamFile.Dispose()的东西吗基于我的代码above@AppleCiderYummy是的,这会起作用,而且您肯定想要处理它,可能是在最后一次尝试中,以防由于某种原因出现异常。但是,如果可能的话,我会避免将
FileStream
作为
DTO
的属性,最好以您需要的方法加载文件流,并使用那里的
语句将其放入
。我理解。但是,在我将
using
语句放在
的电子邮件发送上后,我的电子邮件发送不起作用