He creado Windows Phone 8.1 proyecto y estoy tratando de ejecutar async método GetResponse(string url) en el botón haga clic en y esperando el método para terminar, pero el método es de nunca acabar. Aquí está mi código:

private void Button_Click(object sender, RoutedEventArgs 
{
      Task<List<MyObject>> task = GetResponse<MyObject>("my url");
      task.Wait();
      var items = task.Result; //break point here
}

public static async Task<List<T>> GetResponse<T>(string url)
{
    List<T> items = null;
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

    var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
    try
    {
        Stream stream = response.GetResponseStream();
        StreamReader strReader = new StreamReader(stream);
        string text = strReader.ReadToEnd();
        items = JsonConvert.DeserializeObject<List<T>>(text);
    }
    catch (WebException)
    {
        throw;
    }
    return items;
}

Va a colgar en la tarea.Wait().

He cambiado mi haga clic con el botón método async y utiliza esperan antes de que el método asincrónico y me da el resultado(await GetResponse<string>("url")). Lo que está mal con Task<List<string>> task = GetResponse<string>("url")?
¿Qué estoy haciendo mal?

Gracias por la ayuda!

  • Sólo una pequeña nota, es una convención general que async métodos con el sufijo Async, es decir, su nombre de método sería GetResponseAsync.

3 Comentarios

  1. 81

    Eres la víctima del interbloqueo clásico. task.Wait() o task.Result es una llamada de bloqueo en el subproceso de interfaz de usuario que hace que el interbloqueo.

    No cuadra en el subproceso de interfaz de usuario. Nunca hacerlo. Sólo le esperan.

    private async void Button_Click(object sender, RoutedEventArgs 
    {
          var task = GetResponseAsync<MyObject>("my url");
          var items = await task;
    }

    Por cierto, ¿por qué la captura de la WebException y tirar de la espalda? Sería mejor si simplemente no lo cogen. Ambos son las mismas.

    También veo que estás mezclando el código asincrónico sincrónico con el código dentro de la GetResponse método. StreamReader.ReadToEnd es una llamada de bloqueo-usted debe ser el uso de StreamReader.ReadToEndAsync.

    También el uso de «Async» sufijo para los métodos que se vuelve una Tarea o asincrónica para seguir el GRIFO(«Grupo modelo Asincrónico basado») convención como Jon dice.

    Su método debe ser algo como lo siguiente a la hora de abordar 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);
    }
  2. 25

    Esto es lo que los está matando:

    task.Wait();

    Que bloquea el subproceso de interfaz de usuario hasta que la tarea se ha completado, pero la tarea es un método asincrónico es de la que voy a intentar retomar el subproceso de interfaz de usuario después de «pausa» y espera un async resultado. No puede hacer eso, porque usted bloquea el subproceso de interfaz de usuario…

    No hay nada en el código que realmente parece que necesita para estar en el subproceso de interfaz de usuario de todos modos, pero suponiendo que realmente hacer quieren allí, usted debe utilizar:

    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 simplemente:

    private async void Button_Click(object sender, RoutedEventArgs 
    {
        var items = await GetResponse<MyObject>("my url");
        //Presumably use items here
    }

    Ahora en lugar de el bloqueo de hasta que la tarea se ha completado, el Button_Click método devolverá después de programar una continuación de fuego cuando la tarea se ha completado. (Que es como async/await obras, básicamente.)

    Tenga en cuenta que también me gustaría cambiar el nombre de GetResponse a GetResponseAsync para mayor claridad.

  3. -1

    utilizar a continuación el código

     Task.WaitAll(Task.Run(async () => await GetResponse<MyObject>("my url")));
    • Task.WaitAll bloqueará en la misma manera como task.Wait.
    • la pregunta fue «haga clic en el botón y espera para que el método finish» por lo anterior código snip habrá que esperar hasta el método para finalizar.

Dejar respuesta

Please enter your comment!
Please enter your name here