簡體   English   中英

在 .NET 4.0 下使用 SmtpClient、SendAsync 和 Dispose 的最佳實踐是什么

[英]What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0

現在我對如何管理 SmtpClient 有點困惑,因為它是一次性的,尤其是當我使用 SendAsync 進行調用時。 據推測,在 SendAsync 完成之前我不應該調用 Dispose。 但是我應該稱它為(例如,使用“使用”)。 該場景是一個 WCF 服務,它在進行調用時定期發送電子郵件。 大多數計算速度很快,但發送電子郵件可能需要一秒鍾左右,因此 Async 更可取。

每次發送郵件時都應該創建一個新的 SmtpClient 嗎? 我應該為整個 WCF 創建一個嗎? 幫助!

更新以防萬一,每封電子郵件總是針對用戶進行定制。 WCF 托管在 Azure 上,Gmail 用作郵件程序。

最初的問題是針對 .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 方法。

注意:.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不接受回調有點煩人。

一般來說,IDisposable 對象應該盡快被銷毀; 在對象上實現 IDisposable 旨在傳達這樣一個事實,即所討論的類擁有應該確定性地釋放的昂貴資源。 但是,如果創建這些資源很昂貴並且您需要構造大量這些對象,那么將一個實例保留在內存中並重用它可能會更好(性能方面)。 只有一種方法可以知道這是否有任何區別:對其進行分析!

回復:處置和異步:顯然不能使用using 相反,您通常在 SendCompleted 事件中處置對象:

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

好的,我知道的老問題。 但是當我需要實施類似的東西時,我自己偶然發現了這一點。 我只是想分享一些代碼。

我正在迭代多個 SmtpClient 以異步發送多個郵件。 我的解決方案類似於 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

我在asp.net 5.0核心中使用了這種方式。

public async Task EmailSend(MessageModel messageModel)
    {
        using (MailMessage mailMessage = new MailMessage())
        {
            mailMessage.From = new MailAddress(_configuration.GetSection("EmailConfiguration").GetSection("FromEmail").Value.ToString(), _configuration.GetSection("EmailConfiguration").GetSection("FromName").Value.ToString(), Encoding.UTF8);
            mailMessage.Subject = messageModel.Subject;
            mailMessage.SubjectEncoding = Encoding.UTF8;
            mailMessage.Body = messageModel.Content;
            mailMessage.BodyEncoding = Encoding.UTF8;
            mailMessage.IsBodyHtml = true;
            mailMessage.BodyTransferEncoding = TransferEncoding.Base64;
            mailMessage.To.Add(new MailAddress(messageModel.To));
            NetworkCredential networkCredential = new NetworkCredential(_configuration.GetSection("EmailConfiguration").GetSection("Username").Value.ToString(), _configuration.GetSection("EmailConfiguration").GetSection("Password").Value.ToString());
            SmtpClient smtpClient = new SmtpClient();
            smtpClient.Host = _configuration.GetSection("EmailConfiguration").GetSection("SmtpServer").Value.ToString();
            smtpClient.EnableSsl = Convert.ToBoolean(_configuration.GetSection("EmailConfiguration").GetSection("SSL").Value);
            smtpClient.UseDefaultCredentials = Convert.ToBoolean(_configuration.GetSection("EmailConfiguration").GetSection("UseDefaultCredentials").Value);
            smtpClient.Port = Convert.ToInt32(_configuration.GetSection("EmailConfiguration").GetSection("Port").Value);
            smtpClient.Credentials = networkCredential;
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            await smtpClient.SendMailAsync(mailMessage);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM