.net 异步等待处理程序死锁

.net 异步等待处理程序死锁,.net,async-await,parse-platform,ihttphandler,.net,Async Await,Parse Platform,Ihttphandler,我陷入了异步死锁,无法找到正确的语法来修复它。我已经研究了几种不同的解决方案,但似乎无法完全找出问题的原因 我正在使用作为后端,并尝试使用处理程序写入表。我的处理程序看起来像: public class VisitorSignupHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { //Get the user's name and email address

我陷入了异步死锁,无法找到正确的语法来修复它。我已经研究了几种不同的解决方案,但似乎无法完全找出问题的原因

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

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()
只需等待任务完成,然后返回正常操作。这不正确吗?

您遇到了一个常见的死锁问题,我对此进行了描述和分析

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

要解决这个问题,您应该“一路异步”。在这种情况下,请使用而不是
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;
    ....

  }
}

您的问题是混合了同步和异步代码。这是可以做到的,但很棘手。最好的办法是使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);
..

        }
    }

非常感谢。在发布这篇文章之前,我读了你的博客,只是不太明白其中的语法。这很有效。谢谢你,不客气!附言:好好读一读这本书;这里会用到一些
async
约定,特别是将
SaveUserSignup
重命名为
SaveUserSignupAsync
。您能帮我解决这个问题吗