.net - task run async c#
Async espera del punto muerto del controlador (2)
Estoy atrapado en un punto muerto Async y no puedo encontrar la sintaxis correcta para solucionarlo. He analizado varias soluciones diferentes, pero parece que no puedo entender qué está causando el problema.
Estoy usando Parse como un backend e intento usar un controlador para escribir en la mesa. Mi controlador se ve algo así como:
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; } }
}
Entonces está llamando a mi nivel medio:
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();
}
}
Aunque parece que esto se está estancando en Wait()
. Tenía la impresión de que Wait()
simplemente esperaría a que se completara la tarea y luego volvería a las operaciones normales. ¿Esto no es correcto?
Te encuentras con un problema común de interbloqueo que describo en mi blog y en un artículo reciente de MSDN .
En resumen, await
por defecto que reanude su método async
dentro de un "contexto" capturado, y en ASP.NET, solo se permite un subproceso en ese "contexto" a la vez. Entonces, cuando llamas a Wait
, estás bloqueando un hilo dentro de ese contexto, y el await
no puede ingresar a ese contexto cuando esté listo para reanudar el método async
. Por lo tanto, el hilo en el contexto está bloqueado en Wait
(esperando a que se complete el método async
), y el método async
se bloquea a la espera de que el contexto sea libre ... punto muerto.
Para solucionar esto, debe ir "asincrono todo el camino". En este caso, use HttpTaskAsyncHandler
lugar de 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;
....
}
}
Tu problema es que estás mezclando código síncrono y asíncrono. Esto se puede hacer, pero es complicado. Su mejor opción es hacer que su manejador de http también sea asincrónico:
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);
..
}
}