web-dev-qa-db-fra.com

Appel de la méthode asynchrone au clic du bouton

J'ai créé le projet Windows Phone 8.1 et j'essaie d'exécuter la méthode asynchrone GetResponse (chaîne de caractères) en cliquant sur le bouton et d'attendre la fin de la méthode, mais cette méthode n'est jamais terminée. Voici mon code:

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;
}

Il va accrocher à task.Wait ().

J'ai modifié ma méthode de clic sur le bouton en mode asynchrone et j'ai utilisé l'attente avant la méthode asynchrone et j'ai le résultat (await GetResponse<string>("url")). Quel est le problème avec Task<List<string>> task = GetResponse<string>("url")? Qu'est-ce que je fais mal?

Merci pour l'aide!

36
Doniyor Niyozov

Vous êtes victime de l'impasse classique. task.Wait() ou task.Result est un appel bloquant dans le thread d'interface utilisateur qui provoque le blocage.

Ne bloquez pas dans le fil de l'interface utilisateur . Ne le fais jamais. Attends-le.

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

Au fait, pourquoi attrapez-vous la WebException et la rejetez-vous? Ce serait mieux si vous ne l'attrapez tout simplement pas. Les deux sont les même.

Je peux également constater que vous mélangez le code asynchrone avec le code synchrone dans la méthode GetResponse. StreamReader.ReadToEnd est un appel bloquant - vous devriez utiliser StreamReader.ReadToEndAsync.

Utilisez également le suffixe "Async" pour les méthodes qui renvoie une tâche ou asynchrone conformément à la convention TAP ("Modèle basé sur une tâche") comme Jon dit .

Votre méthode devrait ressembler à ce qui suit lorsque vous avez répondu à toutes les préoccupations ci-dessus.

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);
}
64
Sriram Sakthivel

utiliser ci-dessous le code

 Task.WaitAll(Task.Run(async () => await GetResponse<MyObject>("my url")));
0
Mahesh