Невозможно получить доступ к закрытому потоку при отправке вложения

1

Я пытаюсь отправить электронную почту с вложением с помощью С#. Вот мой метод:

public void SendEmail(string from, string to, SmtpClient client)
    {
        MailMessage mm = new MailMessage(from, to, "Otrzymałeś nowe zamówienie od "+from , "Przesyłam nowe zamówienie na sprzęt");
        mm.BodyEncoding = UTF8Encoding.UTF8;
        mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
        // Adding attachment:

        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);
        writer.Write("Hello its my sample file");
        writer.Flush();
        writer.Dispose();

        System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
        System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
        attach.ContentDisposition.FileName = "myFile.txt";

        mm.Attachments.Add(attach);
        try
        {
            client.Send(mm);
        }
        catch(SmtpException e)
        {
            Console.WriteLine(e.ToString());
        }
        ms.Close();
    }

stacktrace указывает на эту строку:

client.Send(mm);

проблема вызвана этой строкой:

writer.Dispose();

Почему я не могу удалить этот элемент сразу после его использования для записи в MemoryStream? Этот элемент не используется в дальнейшем в коде.

Теги:
smtpclient

3 ответа

4
Лучший ответ

Вызов Dispose на писателе также Dispose базовый поток. После отправки письма вы должны распоряжаться как писателем, так и потоком. Вы можете добиться этого, обернув свой код двумя операциями.

    using(var ms = new System.IO.MemoryStream())
    {
      using(var writer = new System.IO.StreamWriter(ms))
      {
         writer.Write("Hello its my sample file");
         writer.Flush();

         System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
         System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
         attach.ContentDisposition.FileName = "myFile.txt";

         mm.Attachments.Add(attach);
         try
         {
             client.Send(mm);
         }
         catch(SmtpException e)
         {
            Console.WriteLine(e.ToString());
         }
       }
    }
  • 0
    Но как это работает, если у вас есть несколько вложений?
  • 0
    @RayCW хорошо, подготовьте все потоки, отследите их в списке или массиве, если вы не знаете, сколько у вас их, вызовите Attachments. Добавьте для каждого потока, отправьте электронное письмо и, как только завершите вызов, распределяйте по всем вашим вайтерам .и потоки в вашем Списке или Массиве. Использование может больше не быть полезным в этом случае, просто перейдите к try / catch / finally.
Показать ещё 2 комментария
1

Используйте использование блока, как это предлагается в комментариях:

//...
using(System.IO.MemoryStream ms = new System.IO.MemoryStream())
{   
    using(System.IO.StreamWriter writer = new System.IO.StreamWriter(ms))
    {
        writer.Write("Hello its my sample file");
        writer.Flush();

        System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
        System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
        attach.ContentDisposition.FileName = "myFile.txt";

        mm.Attachments.Add(attach);
        client.Send(mm);

    }
} 
1

Когда client.Send пытается отправить его, очевидно, будет прочитано Attachment которое указывает на MemoryStream который уже был закрыт StreamWriter. Вы можете проверить это, ms.CanRead Он вернет false.

Доступ к закрытому потоку вызовет исключение, что вы переживаете. Чтобы решить это, просто избавьтесь от writer.Dispose() поскольку нет ничего, чтобы распоряжаться с MemoryStream или распоряжаться им после завершения вашей работы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню