Solución:
Eres víctima del clásico estancamiento. task.Wait()
o task.Result
es una llamada de bloqueo en el hilo de la interfaz de usuario que provoca el interbloqueo.
No bloquee el hilo de la interfaz de usuario. Nunca hacerlo. Solo espéralo.
private async void Button_Click(object sender, RoutedEventArgs
{
var task = GetResponseAsync<MyObject>("my url");
var items = await task;
}
Por cierto, ¿por qué estás captando el WebException
y tirarlo hacia atrás? Sería mejor si simplemente no lo atrapas. Ambos son lo mismo.
También puedo ver que está mezclando el código asíncrono con el código síncrono dentro del GetResponse
método. StreamReader.ReadToEnd
es una llamada de bloqueo; deberías usar StreamReader.ReadToEndAsync
.
También use el sufijo “Async” para los métodos que devuelven una Task o asynchronous para seguir la convención TAP (“Task based Asynchronous Pattern”) como dice Jon.
Su método debe tener un aspecto similar al siguiente cuando haya abordado todas las preocupaciones anteriores.
public static async Task<List<T>> GetResponseAsync<T>(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
Stream stream = response.GetResponseStream();
StreamReader strReader = new StreamReader(stream);
string text = await strReader.ReadToEndAsync();
return JsonConvert.DeserializeObject<List<T>>(text);
}
Esto es lo que te está matando:
task.Wait();
Eso es bloquear el subproceso de la interfaz de usuario hasta que la tarea se haya completado, pero la tarea es un método asíncrono que intentará volver al subproceso de la interfaz de usuario después de “pausar” y esperar un resultado asíncrono. No puede hacer eso, porque está bloqueando el hilo de la interfaz de usuario …
No hay nada en su código que realmente parezca que necesita estar en el hilo de la interfaz de usuario de todos modos, pero suponiendo que realmente hacer lo quiere allí, debe usar:
private async void Button_Click(object sender, RoutedEventArgs
{
Task<List<MyObject>> task = GetResponse<MyObject>("my url");
var items = await task;
// Presumably use items here
}
O solo:
private async void Button_Click(object sender, RoutedEventArgs
{
var items = await GetResponse<MyObject>("my url");
// Presumably use items here
}
Ahora en lugar de bloqueo hasta que la tarea se haya completado, el Button_Click
El método regresará después de programar una continuación para que se active cuando la tarea se haya completado. (Así es como funciona async / await, básicamente).
Tenga en cuenta que también cambiaría el nombre GetResponse
para GetResponseAsync
para mayor claridad.