2013-07-25 131 views
7

我被困在异步死锁,我找不出正确的语法来解决它。我看过几种不同的解决方案,但似乎无法弄清楚是什么导致了这个问题。异步等待处理程序死锁

我使用Parse作为后端,并尝试使用处理程序写入表。我的处理程序看起来像:

public class VisitorSignupHandler : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     //Get the user's name and email address 
     var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
     var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

     //Save the user's information 
     var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
     TaskToken.Wait(); 
     .... 

    } 

    public bool IsReusable { get { return false; } } 
} 

然后,它呼唤我的中间层:

public static class UserSignup 
{ 
    public static async Task SaveUserSignup(string fullName, string emailAddress) 
    { 
     //Initialize the Parse client with the Application ID and the Windows key 
     ParseClient.Initialize(AppID, Key); 

     //Create the object 
     var UserObject = new ParseObject("UserSignup") 
          { 
           {"UserFullName", fullName}, 
           {"UserEmailAddress", emailAddress} 
          }; 

     //Commit the object 
     await UserObject.SaveAsync(); 
    } 
} 

尽管这似乎是陷入在Wait()。我的印象是,Wait()只是等待任务完成,然后返回到正常操作。这是不正确的?

回答

13

您遇到了一个常见的死锁问题,我描述了on my blogin a recent MSDN article

简而言之,默认情况下,await将在捕获的“上下文”内恢复其async方法,并且在ASP.NET上,一次只允许一个线程进入该“上下文”。因此,当您拨打Wait时,您将阻止该环境中的线程,并且在准备好恢复async方法时,await无法进入该环境。因此,上下文中的线程被阻止在Wait(等待async方法完成),并且async方法被阻止,等待上下文被释放......死锁。

要解决这个问题,你应该“一路异步”。在这种情况下,使用HttpTaskAsyncHandler代替IHttpHandler

public class VisitorSignupHandler : HttpTaskAsyncHandler 
{ 
    public override async Task ProcessRequestAsync(HttpContext context) 
    { 
    //Get the user's name and email address 
    var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
    var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

    //Save the user's information 
    var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
    await TaskToken; 
    .... 

    } 
} 
+0

谢谢!我在发布之前先阅读您的博客,但无法完全弄清楚语法。这很好。欣赏它。 –

+1

不客气!附:给[TAP文档](http://msdn.microsoft.com/en-us/library/hh873175.aspx)一个很好的阅读;这里有一些'async'约定,特别是将'SaveUserSignup'重命名为'SaveUserSignupAsync'。 –

1

你的问题是,你是混合式同步和异步代码。这可以完成,但很棘手。你最好的选择是让你的http处理器异步:

public class VisitorSignupHandler : HttpTaskAsyncHandler 
    { 
     public override async Task ProcessRequestAsync(HttpContext context) 
     { 
      //Get the user's name and email address 
      var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
      var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

      //Save the user's information 
      await UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
.. 

     } 
    }