Async Await Handler Deadlock

断了今生、忘了曾经 提交于 2019-12-25 09:43:06

问题


I'm stuck in an Async deadlock and I can't figure out the correct syntax to fix it. I've looked at several different solutions, but can't seem to quite figure out what is causing the problem.

I am using Parse as a backend and trying to use a handler to write to the table. My handler looks something like:

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

Then it is calling my middle tier:

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

Although this seems to be getting stuck at Wait(). I was under the impression that Wait() would simply just wait for the task to complete, then return to normal operations. Is this not correct?


回答1:


You're running into a common deadlock problem that I describe on my blog and in a recent MSDN article.

In short, await by default will resume its async method inside of a captured "context", and on ASP.NET, only one thread is allowed into that "context" at a time. So when you call Wait, you are blocking a thread inside that context, and the await cannot enter that context when it is ready to resume the async method. So the thread in the context is blocked at Wait (waiting for the async method to complete), and the async method is blocked waiting for the context to be free... deadlock.

To fix this, you should go "async all the way". In this case, use HttpTaskAsyncHandler instead of 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;
    ....

  }
}



回答2:


Your problem is that you are mixing synchronous and async code. This can be done, but is tricky. Your best bet is to make your http handler async as well:

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);
..

        }
    }


来源:https://stackoverflow.com/questions/19962100/task-run-not-blocking-and-not-continuing-the-code-below

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!