Каковы рекомендации по использованию SmtpClient, SendAsync и Dispose under.NET 4.0


Я немного озадачен тем, как управлять SmtpClient теперь, когда он доступен, особенно если я делаю звонки с помощью SendAsync. Предположительно, Я не должен вызывать Dispose до завершения SendAsync. Но должен ли я когда-либо называть его (например, используя "использование"). Сценарий-это служба WCF, которая периодически отправляет электронную почту при выполнении вызовов. Большая часть вычислений выполняется быстро, но отправка электронной почты может занять секунду или около того, поэтому асинхронность была бы предпочтительнее.

должен ли я создать новый SmtpClient каждый раз, когда я отправляю почту? Должен ли я создать один для всего WCF? Помогите!

обновление в случае, если это имеет значение, каждое письмо всегда настроен для пользователя. WCF размещается в Azure, а Gmail используется в качестве почтовой программы.

5 94

5 ответов:

Примечание: .NET 4.5 SmtpClient реализует async awaitable метод SendMailAsync. Для более низких версий используйте SendAsync, как описано ниже.


вы всегда должны распоряжаться IDisposable случаи, при первой же возможности. В случае асинхронных вызовов это происходит при обратном вызове после отправки сообщения.

var message = new MailMessage("from", "to", "subject", "body"))
var client = new SmtpClient("host");
client.SendCompleted += (s, e) => {
                           client.Dispose();
                           message.Dispose();
                        };
client.SendAsync(message, null);

это немного раздражает SendAsync не принимает обратный вызов.

исходный вопрос был задан для .NET 4, но если он помогает с .NET 4.5 SmtpClient реализует асинхронный ожидаемый метод SendMailAsync.

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

public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage)
{
    using (var message = new MailMessage())
    {
        message.To.Add(toEmailAddress);

        message.Subject = emailSubject;
        message.Body = emailMessage;

        using (var smtpClient = new SmtpClient())
        {
            await smtpClient.SendMailAsync(message);
        }
    }
}

лучше избегать использования метода SendAsync.

Re: утилизация и асинхронность: вы не можете использовать using очевидно. Вместо этого вы обычно размещаете объект в событии SendCompleted:

var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => smtpClient.Dispose();
smtpClient.SendAsync(...);

хорошо, старый вопрос я знаю. Но я сам наткнулся на это, когда нуждался в реализации чего-то подобного. Я просто хотел поделиться некоторым кодом.

Я перебираю несколько SmtpClients, чтобы отправить несколько писем асинхронно. Мое решение похоже на TheCodeKing, но вместо этого я удаляю объект обратного вызова. Я также передаю MailMessage как userToken, чтобы получить его в событии SendCompleted, чтобы я мог также вызвать dispose. Вот так:

foreach (Customer customer in Customers)
{
    SmtpClient smtpClient = new SmtpClient(); //SmtpClient configuration out of this scope
    MailMessage message = new MailMessage(); //MailMessage configuration out of this scope

    smtpClient.SendCompleted += (s, e) =>
    {
        SmtpClient callbackClient = s as SmtpClient;
        MailMessage callbackMailMessage = e.UserState as MailMessage;
        callbackClient.Dispose();
        callbackMailMessage.Dispose();
    };

    smtpClient.SendAsync(message, message);
}

вы можете понять, почему особенно важно избавиться от SmtpClient с помощью следующего комментария:

public class SmtpClient : IDisposable
   // Summary:
    //     Sends a QUIT message to the SMTP server, gracefully ends the TCP connection,
    //     and releases all resources used by the current instance of the System.Net.Mail.SmtpClient
    //     class.
    public void Dispose();

в моем сценарии отправки нескольких писем с помощью Gmail без утилизации клиента, я использовал, чтобы получить:

сообщение: услуга недоступна, закрытие канала передачи. Этот ответ сервера был: 4.7.0 временная системная проблема. Повторите попытку позже (WS). oo3sm17830090pdb.64-gsmtp