Tengo una llamada que estoy haciendo desde dentro de una C#
aplicación de metro basada en xaml en el Win8 CP; esta llamada simplemente llega a un servicio web y devuelve datos JSON.
HttpMessageHandler handler = new HttpClientHandler();
HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");
var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);
Se cuelga en el await
pero la llamada http realmente regresa casi inmediatamente (confirmado a través de Fiddler) es como si await
se ignorara y simplemente se cuelga allí.
Antes de preguntar , SÍ, la función de red privada está activada.
¿Alguna idea de por qué esto colgaría?
c#
asynchronous
async-await
dotnet-httpclient
keithwarren7
fuente
fuente
async
método? ¿No lanza una excepción?Respuestas:
Mira esta respuesta a mi pregunta que parece ser muy similar.
Algo para probar: invocar
ConfigureAwait(false)
la tarea devuelta porGetStreamAsync()
. P.ejSi esto es útil o no depende de cómo se llame a su código anterior; en mi caso, llamar al
async
método usandoTask.GetAwaiter().GetResult()
causó que el código se bloqueara.Esto se debe a que
GetResult()
bloquea el hilo actual hasta que se completa la tarea. Cuando la tarea se completa, intenta volver a ingresar al contexto del hilo en el que se inició, pero no puede porque ya hay un hilo en ese contexto, que está bloqueado por la llamada aGetResult()
... ¡punto muerto!Esta publicación de MSDN detalla un poco cómo .NET sincroniza subprocesos paralelos, y la respuesta a mi propia pregunta brinda algunas de las mejores prácticas.
fuente
Solo un aviso: si pierde la espera en el nivel superior en un controlador ASP.NET, y devuelve la tarea en lugar del resultado como respuesta, en realidad simplemente se bloquea en las llamadas de espera anidadas sin errores. Un error tonto, pero si hubiera visto esta publicación, podría haberme ahorrado algo de tiempo revisando el código en busca de algo extraño.
fuente
Descargo de responsabilidad: no me gusta la solución ConfigureAwait () porque la encuentro no intuitiva y difícil de recordar. En cambio, llegué a la conclusión de envolver las llamadas de método no esperadas en Task.Run (() => myAsyncMethodNotUsingAwait ()). ¡Esto parece funcionar al 100%, pero podría ser solo una condición de carrera !? Para ser honesto, no estoy tan seguro de lo que está pasando. Esta conclusión puede ser incorrecta y me arriesgo a que mis puntos StackOverflow aquí para aprender de los comentarios :-P. ¡Por favor léalos!
Acabo de tener el problema como se describe y encontré más información aquí .
La declaración es: "no puedes llamar a un método asincrónico"
de un método que bloquea
En mi caso, no pude cambiar el método de llamada y no fue asincrónico. Pero en realidad no me importaba el resultado. Según recuerdo, tampoco funcionó al eliminar el .Result y falta la espera.
Entonces hice esto:
En mi caso, no me importó el resultado de la llamada al método no asíncrono, pero supongo que es bastante común en este caso de uso. Puede utilizar el resultado en el método asincrónico de llamada.
fuente