Joh*_*n L 8 c# asynchronous smtpclient
这里简单的概念.这适用于使用MVC 3和Entity Framework 4构建的站点.用户在站点上注册后,会向其电子邮件地址发送一封电子邮件.我首先使用SmtpClient.Send()实现它,它工作正常.然后我明白了尝试异步发送电子邮件.我遇到了我尝试过的两种异步方法的问题.
第一个实现(来自这个未回答的帖子: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);
}
}
Run Code Online (Sandbox Code Playgroud)
这有一半的时间.另一半我会在CallBack中收到"无法访问已处置对象"错误.
下一个实现(来自具有良好声誉的成员:在.NET 4.0下使用SmtpClient,SendAsync和Dispose的最佳实践):
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);
Run Code Online (Sandbox Code Playgroud)
有了这个实现,我没有得到任何错误,但是当执行smtpClient.SendAsync()时,在调试模式下有明显更长的延迟(~5秒),这使我认为它不是异步发送的.
问题:
1)导致"处置对象"错误的第一种方法出了什么问题?
2)第二个实现是否存在导致电子邮件不异步发送的问题?5秒延迟是无意义的吗?
可能还需要注意的是,虽然该网站不需要支持发送大量电子邮件(仅限用户注册,选择加入新闻通讯等),但我们预计将来会有大量用户,因此我决定异步发送电子邮件.
谢谢.
提示:1 - 不要对MailMessage对象使用"using block",它会在邮件发送之前处理您的对象,
在SmtpClient.SendCompleted事件上发送2-dispose MailMessage对象:
smtpClient.SendCompleted += (s, e) =>
{
message.Dispose();
};
Run Code Online (Sandbox Code Playgroud)
用于smtpClient对象的3组SendCompletedEventHandler
smtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
Run Code Online (Sandbox Code Playgroud)
4个代码:
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this asynchronous operation.
String token = (string)e.UserState;
if (e.Cancelled)
{
//write your code here
}
if (e.Error != null)
{
//write your code here
}
else //mail sent
{
//write your code here
}
mailSent = true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17381 次 |
| 最近记录: |