我有一个WebApi控制器,其中一个部件是向一组用户发送电子邮件。
[HttpPost]
[Authorize]
[Route("{id}/Do")]
public async Task<HttpResponseMessage> Post(int id, Model model)
...
await _emailService.SendAsync(message);
...现在,发送电子邮件的方法(SendGrid)
public override async Task SendAsync(MailMessage message)
{
var client =
new SmtpClient(SendGridServerName, SendGridServerPort)
{
Port = SendGridServerPort,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false
};
var credentials = new NetworkCredential(SendGridUserName, SendGridPassword);
client.EnableSsl = true;
client.Credentials = credentials;
message.From = new MailAddress(FromAddress);
await client.SendMailAsync(message);
}一切正常,但速度很慢。我原以为它会很快,但是await _emailService.SendAsync(message);看起来并不是异步的。在那里停了一段时间。
有什么想法吗?
谢谢
发布于 2015-05-18 08:33:09
async所做的是允许服务器在缓慢的方法异步执行时运行其他线程。也就是说,当您对异步方法执行await时,服务器执行一个不同的线程,直到async方法完成执行,然后继续运行调用异步方法的线程。控制器中的异步操作在幕后处理的方式完全相同。因此,在async电子邮件发送完成之前,不会发生从async操作到浏览器的响应。
注意:例如,如果与电子邮件服务器或DNS解析有连接问题,通常30秒后就会超时,所以线程将在30秒内休眠,然后才会将答案发送给浏览器。
如果您想快速返回浏览器的响应,您需要实现一个不同的想法,即启动一个发送电子邮件的新线程,但不要等待它完成,这样您的线程就会继续运行,并立即将asnwer返回给浏览器。这就是所谓的火和遗忘。要理解我说的是什么,请看这个:Fire and forget approach。然后仔细阅读另一个:Fire and Forget (Asynch) ASP.NET Method Call。考虑到MVC本身是线程的,在使用fire和忘记方法时,您需要考虑它。
显然,在火和忘记,控制器将无法检测错误的电子邮件发送,因为新的线程运行它自己,而主线程已经完成。因此,您必须实现一些至少记录可能发生的错误的东西,并且最好让用户现在就知道发生了什么(例如,他稍后可以看到的报告)。请看这个:ASP.NET Exception Handling in background threads
https://stackoverflow.com/questions/30277061
复制相似问题