第一个实现方法(来自这篇未回答的帖子:https://stackoverflow.com/questions/7558582/how-to-dispose-using-smtpclient-send-and-asynccallback):
public bool Emailer(){
.
.
.
using (var smtpClient = new SmtpClient())
{
smtpClient.EnableSsl = true;
smtpClient.Host = "smtp.gmail.com";
smtpClient.Port = 587;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential("myaddress@gmail.com", "mypassword");
var sd = new SendEmailDelegate(smtpClient.Send);
var cb = new AsyncCallback(SendEmailResponse);
sd.BeginInvoke(message, cb, sd);
return true;
}
}
private delegate void SendEmailDelegate(System.Net.Mail.MailMessage m);
private static void SendEmailResponse(IAsyncResult ar)
{
try
{
SendEmailDelegate sd = (SendEmailDelegate)(ar.AsyncState);
sd.EndInvoke(ar); // "cannot access a disposed object" errors here
}
catch (Exception e)
{
_logger.WarnException("Error on EndInvoke.", e);
}
}
这个方法有时候有效,但是另一半时间我会在回调函数中遇到"Cannot access a disposed object"的错误。
下一个实现(来自一个信誉良好的成员:What are best practices for using SmtpClient, SendAsync and Dispose under .NET 4.0):
var smtpClient = new SmtpClient();
smtpClient.EnableSsl = true;
smtpClient.Host = "smtp.gmail.com";
smtpClient.Port = 587;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential("myaddress@gmail.com", "mypassword");
smtpClient.SendCompleted += (s, e) =>
{
smtpClient.Dispose();
message.Dispose();
};
smtpClient.SendAsync(message, null);
使用这种实现方法没有出现任何错误,但是在调试模式下smtpClient.SendAsync()执行时有明显的延迟(约5秒),这使我认为它没有异步发送。
问题:
1)第一种方法中有什么问题会导致“disposed object”错误?
2)第二种实现方式是否存在导致电子邮件无法异步发送的问题?5秒的延迟是否无意义?
还值得注意的是,虽然该站点不需要支持发送大量电子邮件(仅用户注册、选择接收新闻通讯等),但我们预计未来会有大量用户,因此我决定异步发送电子邮件。
谢谢。