2013-01-02 45 views
1

仅仅因为某些工作并不意味着它是正确的。所以我想就下面的代码提供一些反馈。异步ActionMethod - 这是否正确

有点历史;当用户在我们的网站上注册时,我试图发送/排队电子邮件,并遇到线程被阻塞的问题,鉴于控制器默认情况下和相关联的操作方法是同步而不是异步的,这是完全合理的。为了解决这个问题,我把以下内容放在一起,但我不确定它是否是最好的方法。

[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"); 
    } 
+0

你的问题到底是什么?询问代码是否“好或不好”是模糊的。 – GraphicsMuncher

+0

这是处理发送电子邮件的正确方法。或者会在稍后导致我的问题。 – SnakeEyes

回答

2

我不知道什么样的“问题”可能是由ASP.NET线程被阻塞引起的,而是关于你async/await代码:

  • 有没有点new CancellationToken(false),与CancellationToken.None相同,与仅提供cancellationToken参数相同。
  • 可能没有指向Task.Run,它在线程池线程上执行SendAsync。如果SendAsync是一个合适的方法,那么它可以直接编辑0​​。

    await _userMailer.RegistrationConfirmation(user).SendAsync(); 
    

    编辑:

例如,该行代码可以被替代

由于SendAsyncSmtpClient,你应该wrap this API(使用Event-based Asynchronous Pattern)到await - (使用Task-based Asynchronous Pattern):

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; 
} 

然后你可以awaitSmtpClient.SendTaskAsync的结果。

你不想使用Task.Run,因为这会导致你return early from ASP.NET requests, which is a dangerous practice(正如我在我的博客上解释的)。

+0

我收到一条错误消息,指出无法执行操作。线程被阻塞,这是原因。 – SnakeEyes

+0

在这种情况下,问题可能出在'SendAsync'上。 –

+0

我会尝试使用SmtpClient的SendAsync直接进行验证。 – SnakeEyes