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?
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;
....
}
}
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/17859898/async-await-handler-deadlock