Saltar al contenido

Llamar al método asíncrono al hacer clic en el botón

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *