在.net 4.0下使用SmtpClient, SendAsync和Dispose的最佳实践是什么?
本文关键字:最佳 Dispose 是什么 SendAsync 0下 net SmtpClient | 更新日期: 2023-09-27 18:07:21
我对如何管理SmtpClient有点困惑,因为它是一次性的,特别是如果我使用SendAsync进行调用。大概我不应该调用Dispose直到SendAsync完成。但我是否应该这样称呼它(例如,用"using")。该场景是一个WCF服务,它在进行呼叫时定期发送电子邮件。大多数计算都很快,但发送电子邮件可能需要一秒钟左右的时间,所以Async更可取。
我应该在每次发送邮件时创建一个新的SmtpClient吗?我应该为整个WCF创建一个吗?的帮助!
Update以防万一,每个电子邮件总是为用户定制的。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的目的是传达这样一个事实,即所讨论的类持有应该确定释放的昂贵资源。但是,如果创建这些资源的成本很高,并且需要构造很多这样的对象,那么在内存中保留一个实例并重用它可能会更好(性能方面)。只有一种方法可以知道这是否有任何区别:分析它!
Re: dispose和Async:你显然不能使用using
。相反,您通常在SendCompleted事件中处置对象:
var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => smtpClient.Dispose();
smtpClient.SendAsync(...);
好吧,我知道这个老问题。但当我需要实现类似的东西时,我自己偶然发现了这一点。我只是想分享一些代码。
我在几个smtpclient上迭代以异步发送几封邮件。我的解决方案类似于theecodeking,但我要处理回调对象。我也传递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 core中使用了这种方法。
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);
}
}