【发布时间】:2018-07-10 18:09:27
【问题描述】:
我正在创建每 5 分钟发送一批电子邮件的 Windows 服务。
我想每 5 分钟分批发送 10-100 封电子邮件。这是极端情况。批次每 5 分钟发送一次,通常最多包含 10 封电子邮件。
我正在使用 System.Net.Mail 命名空间中的 SmtpClient。
什么是 SmtpClient 对象的正确生命周期? 我应该在每次发送批次时创建一个吗? 或者我应该在服务启动时创建一个并且从不丢弃它?
【问题讨论】:
我正在创建每 5 分钟发送一批电子邮件的 Windows 服务。
我想每 5 分钟分批发送 10-100 封电子邮件。这是极端情况。批次每 5 分钟发送一次,通常最多包含 10 封电子邮件。
我正在使用 System.Net.Mail 命名空间中的 SmtpClient。
什么是 SmtpClient 对象的正确生命周期? 我应该在每次发送批次时创建一个吗? 或者我应该在服务启动时创建一个并且从不丢弃它?
【问题讨论】:
您应该始终使用using
using (var smtpClient = new SmtpClient())
{
smtpClient.SendMail(message);
}
在大多数情况下,您应该始终在完成任何实现IDisposable 的东西后立即处理它,但是您应该始终检查文档以确定。 .NET 4.0 中的SmtpClient 类实现了IDisposable,所以一定要使用它!
引用 MSDN:
SmtpClient 类没有 Finalize 方法,因此应用程序必须 调用 Dispose 以显式释放资源。
如果您发现自己在执行与异步相关的任务,则可以为每封电子邮件创建一个新实例以防止自己被屏蔽。您可以使用以下方法。
var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => {
client.Dispose();
message.Dispose();
};
client.SendAsync(message, null);
应要求 - 批量发送电子邮件的最佳选择
如上所述,您可以重复使用同一个客户端。如果您将所有内容都放在同一个线程上,我建议您只使用一个客户端
MSDN 状态:
SmtpClient 类实现池 SMTP 连接,以便它 可以避免每次重新建立连接的开销 消息发送到同一服务器。 应用程序可以重复使用相同的 SmtpClient 对象将许多不同的电子邮件发送到同一个 SMTP 服务器和许多不同的 SMTP 服务器。
但它继续说:
...因此,无法确定应用程序何时 使用完 SmtpClient 对象,应该清理它。
所以假设您在完成后处理掉您的客户。
因为我最近发现自己在问同样的问题,所以下面链接了许多与 SMTP 相关的主题的讨论
更多来自 Stackoverflow:
What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0
How to dispose objects having asynchronous methods called?
相关阅读:
Implementing Finalize and Dispose to clean up managed resources
【讨论】:
从 .NET 4.0 开始,SmtpClient 将连接池化,因此您可以使用它一段时间。最好在发送完一批后将其丢弃。
来自 MSDN:https://msdn.microsoft.com/en/us/library/system.net.mail.smtpclient(v=VS.100).aspx
SmtpClient 类实现池化 SMTP 连接,这样它就可以避免为每条消息重新建立到同一服务器的连接的开销。应用程序可以重复使用相同的 SmtpClient 对象将许多不同的电子邮件发送到同一个 SMTP 服务器和许多不同的 SMTP 服务器。因此,无法确定应用程序何时使用 SmtpClient 对象完成并且应该对其进行清理。
【讨论】:
首先,在需要时使用任何对象是一种非常好的做法,除非您在整个应用程序中都需要它的实用程序。
其次,您应该在每次需要时创建 SmtpClient 的对象并正确处理它,为此使用 Glitch100 上面描述的 using 标签。
using (var smtpClient = new SmtpClient())
{
smtpClient.SendMail(message);
}
【讨论】: