Asp.net Async ActionMethod-是否正确
仅仅因为某些东西有效并不意味着它是正确的。因此,我想就以下代码获得一些反馈 一点历史;我试图发送/排队电子邮件时,一个用户在我们的网站上注册,遇到了一个线程被阻止的问题,这完全有道理,因为默认情况下控制器和关联的操作方法是同步而非异步的。为了解决这个问题,我总结了以下内容,但不确定这是否是最好的方法Asp.net Async ActionMethod-是否正确,asp.net,asp.net-mvc-4,Asp.net,Asp.net Mvc 4,仅仅因为某些东西有效并不意味着它是正确的。因此,我想就以下代码获得一些反馈 一点历史;我试图发送/排队电子邮件时,一个用户在我们的网站上注册,遇到了一个线程被阻止的问题,这完全有道理,因为默认情况下控制器和关联的操作方法是同步而非异步的。为了解决这个问题,我总结了以下内容,但不确定这是否是最好的方法 [HttpPost, AllowAnonymous] public async Task<ActionResult> RegisterAsync(UserRegisterUse
[HttpPost, AllowAnonymous]
public async Task<ActionResult> RegisterAsync(UserRegisterUserViewModel userRegisterUserViewModel)
{
if (ModelState.IsValid)
{
var user = new UserDto
{
UserName = userRegisterUserViewModel.UserName,
Password = userRegisterUserViewModel.Password,
AuthType = userRegisterUserViewModel.AuthType,
Active = 0
};
Guid userId = _userService.AddUser(user);
if (userId != Guid.Empty)
{
// Send Registration E-mail
await Task.Run(() => _userMailer.RegistrationConfirmation(user).SendAsync(),
new CancellationToken(false));
// Display Confirm View
return PartialView("_RegistrationConfirmation");
}
ModelState.AddModelError("UserName", "Unable to create account");
}
return PartialView("_Registration");
}
[HttpPost,AllowAnonymous]
公共异步任务注册表同步(UserRegisterUserServiewModel UserRegisterUserServiewModel)
{
if(ModelState.IsValid)
{
var user=new UserDto
{
UserName=userRegisterUserServiceWModel.UserName,
Password=userRegisterUserServiewModel.Password,
AuthType=UserRegisterUserServiewModel.AuthType,
活动=0
};
Guid userId=\u userService.AddUser(用户);
if(userId!=Guid.Empty)
{
//发送注册电子邮件
等待任务。运行(()=>_userMailer.RegistrationConfirmation(user.SendAsync(),
新的CancellationToken(false));
//显示确认视图
返回部分视图(“注册确认”);
}
AddModelError(“用户名”,“无法创建帐户”);
}
返回部分视图(“U注册”);
}
我不确定ASP.NET线程被阻塞会导致什么样的“问题”,但关于您的异步
/等待代码:
new CancellationToken(false)
没有意义,这与CancellationToken相同。None
,这与不提供CancellationToken
参数相同
- 可能没有指向
Task.Run
,它在线程池线程上执行SendAsync
。如果SendAsync
是一种合适的async
方法,那么可以直接wait
e、 例如,该代码行可以替换为:
await _userMailer.RegistrationConfirmation(user).SendAsync();
编辑:
由于SendAsync
在SmtpClient
上,因此您应该(使用)进入等待
友好的API(使用):
公共静态任务SendTaskAsync(此SmtpClient客户端,邮件消息)
{
var tcs=new TaskCompletionSource();
SendCompletedEventHandler=null;
处理程序=(s,e)=>
{
client.sendpleted-=处理程序;
如果(e.Error!=null)tcs.TrySetException(e.Error);
否则,如果(如取消)tcs.TrySetCanceled();
else tcs.TrySetResult(null);
};
client.sendpleted+=处理程序;
client.SendAsync(消息,null);
返回tcs.Task;
}
然后您可以等待SmtpClient.SendTaskAsync
的结果
你不想使用任务。运行,因为这会导致你(正如我在博客上解释的那样)。你的问题到底是什么?询问代码是否“好”是含糊不清的。这是处理电子邮件发送的正确方法吗。或者它会导致我以后出现问题。我收到一个错误,说明无法执行该操作。线程被阻止,这就是原因。在这种情况下,问题可能出在sendsync
中。我将尝试直接从SmtpClient使用sendsync进行验证。类似的问题,现在我收到一个消息,说明异步模块或处理程序已完成,而异步操作仍处于挂起状态。我不能使用你的行:wait_userMailer.RegistrationConfirmation(user.SendAsync();它是空的。不能在空虚中等待。然而,Task.Run修复了这个问题。Is client.sendpleted-=handler;应该在外面的某个地方初始化。我得到一个错误,指出局部变量“handler”在访问之前可能没有初始化。
public static Task SendTaskAsync(this SmtpClient client, MailMessage message)
{
var tcs = new TaskCompletionSource<object>();
SendCompletedEventHandler handler = null;
handler = (s,e) =>
{
client.SendCompleted -= handler;
if (e.Error != null) tcs.TrySetException(e.Error);
else if (e.Cancelled) tcs.TrySetCanceled();
else tcs.TrySetResult(null);
};
client.SendCompleted += handler;
client.SendAsync(message, null);
return tcs.Task;
}