Quelles sont les meilleures pratiques pour utiliser SmtpClient, SendAsync et Dispose sous .NET 4.0

Je suis un peu perplexe sur la façon de gérer SmtpClient maintenant qu’il est jetable, surtout si je passe des appels avec SendAsync. Je suppose que je ne devrais pas appeler Dispose avant que SendAsync ne soit terminé. Mais devrais-je jamais l’appeler (par exemple, en utilisant “using”). Le scénario est un service WCF qui envoie régulièrement des e-mails lorsque des appels sont effectués. La plupart des calculs sont rapides, mais l’envoi de courrier électronique peut prendre une seconde, alors Async serait préférable.

Dois-je créer un nouveau SmtpClient chaque fois que j’envoie un mail? Dois-je en créer un pour l’ensemble de la WCF? Aidez-moi!

Mise à jour Si cela fait une différence, chaque email est toujours personnalisé pour l’utilisateur. Le WCF est hébergé sur Azure et Gmail est utilisé comme mailer.

Remarque: .NET 4.5 SmtpClient implémente la méthode async awaitable SendMailAsync . Pour les versions inférieures, utilisez SendAsync comme décrit ci-dessous.


Vous devez toujours disposer des instances IDisposable le plus tôt possible. Dans le cas d’appels asynchrones, il s’agit du rappel après l’envoi du message.

 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); 

C’est un peu agaçant que SendAsync n’accepte pas un rappel.

La question d’origine a été posée pour .NET 4, mais si elle est utile à partir de .NET 4.5, SmtpClient implémente la méthode asynchrone SendMailAsync .

En conséquence, l’envoi de courrier électronique de manière asynchrone est le suivant:

 public async Task SendEmail(ssortingng toEmailAddress, ssortingng emailSubject, ssortingng 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); } } } 

Il est préférable d’éviter d’utiliser la méthode SendAsync.

En général, les objects identifiables doivent être éliminés le plus rapidement possible. implémenter IDisposable sur un object est destiné à communiquer le fait que la classe en question contient des ressources coûteuses qui doivent être libérées de manière déterministe. Cependant, si la création de ces ressources est coûteuse et que vous devez construire beaucoup de ces objects, il peut être préférable (en termes de performances) de conserver une instance en mémoire et de la réutiliser. Il n’y a qu’une seule façon de savoir si cela fait une différence: profilez-le!

Re: disposer et Async: vous ne pouvez pas utiliser évidemment. Au lieu de cela, vous disposez généralement de l’object dans l’événement SendCompleted:

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

Ok, vieille question que je connais. Mais je suis tombé dessus moi-même quand j’avais besoin de mettre en œuvre quelque chose de similaire. Je voulais juste partager du code.

Je parcourt plusieurs SmtpClients pour envoyer plusieurs messages de manière asynchrone. Ma solution est similaire à TheCodeKing, mais je dispose plutôt de l’object callback. Je passe également MailMessage en tant que userToken pour l’obtenir lors de l’événement SendCompleted. Comme ça:

 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); } 

Vous pouvez voir pourquoi il est particulièrement important de disposer de SmtpClient par le commentaire suivant:

 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(); 

Dans mon scénario, l’envoi de plusieurs mails via Gmail sans disposer du client, j’avais l’habitude:

Message: Service non disponible, fermeture du canal de transmission. La réponse du serveur était: 4.7.0 Problème temporaire du système. Réessayez plus tard (WS). oo3sm17830090pdb.64 – gsmtp