我正在尝试从Controller异步发送电子邮件,并收到以下错误:
我不想等待发送电子邮件完成操作。
异步完成的异步模块或处理程序
操作仍在进行中。
这是我的实现:我也尝试使用void
代替async Task
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
var user = await _userManager.FindByNameAsync(model.Email);
if (user != null)
{
if (!await _userManager.IsEmailConfirmedAsync(user.Id))
{
//dont want to await result
//just send email
_mailService.SendAccountConfirmationEmailAsync(user);
...
}
...
}
return View();
}
。
public async Task SendAccountConfirmationEmailAsync(ApplicationUser user)
{
dynamic email = GetAccountConfirmationEmailTemplate();
email.Username = user.Email;
email.Name = user.UserName;
email.To = user.Email;
email.AccountConfirmationUrl = await GetAccountConfirmationUrl(user);
await _mailService.SendAsync(email);
}
我想念什么?
最佳答案
由于运行时知道知道没有其他待处理的请求时可以循环使用您的appdomain,因此特别不建议您启动不等待的任务,因此该消息是不建议的。
特别是,没有此检查,您将无法保证会发送此电子邮件,因为在您的控制器操作返回后,整个appdomain可能会围绕该任务被删除。
现在,您可能会说丢失电子邮件是可以接受的,但是运行时并不知道这只是一封电子邮件,这很可能是您忘记等待的数据库调用过早了流产了。因此,它只是告诉您这是错误的形式。
相反,您有两种选择:
等待该任务完成,您已经明确表示您不想做
通知运行时您正在执行您特别不想等待的任务,但是请哦,拜托,请不要在任务完成前退出appdomain
这最后一部分是HostingEnvironment.QueueBackgroundWorkItem的用途。
在您的情况下,您可以这样称呼它:
HostingEnvironment.QueueBackgroundWorkItem(ct =>
_mailService.SendAccountConfirmationEmailAsync(user));
此外,该方法提供了
CancellationToken
,您应该检查是否有SendAccountConfirmationEmailAsync
的重载接受它。如果不是,并且这是您的API,则应考虑添加对此类令牌的支持。请注意,这种机制并不适合长时间运行的线程或任务,因为还有其他更合适的树可以吠叫,但在这种情况下,它就足够了。
关于c# - 发送电子邮件异步:异步模块或处理程序在异步操作仍处于挂起状态时完成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44422556/