web-dev-qa-db-fra.com

appeler la méthode asynchrone sans attendre # 2

J'ai une méthode asynchrone:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

J'appelle cette méthode comme ceci:

bool isValid = await ValidateRequestAsync("user1", "pass1");

Puis-je appeler la même méthode à partir d'une méthode synchrone, sans utiliser le mot clé await?

Ex:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

Je pense que cela entraînera une impasse.

MODIFIER

L'appel de la méthode comme ci-dessus rend l'appel sans fin. (La méthode n'atteint plus la fin)

40
Catalin

Si vous appelez une méthode asynchrone à partir d'un contexte d'exécution à thread unique, tel qu'un thread d'interface utilisateur, et attendez le résultat de manière synchrone, il y a une forte probabilité de blocage. Dans votre exemple, cette probabilité est de 100%

Penses-y. Que se passe-t-il lorsque vous appelez

ValidateRequestAsync(userName, password).Result

Vous appelez la méthode ValidateRequestAsync. Là, vous appelez ReadAsStringAsync. Le résultat est qu'une tâche sera renvoyée au thread d'interface utilisateur, avec une poursuite planifiée pour continuer à s'exécuter sur le thread d'interface utilisateur lorsqu'elle sera disponible. Mais bien sûr, il ne sera jamais disponible, car il attend (bloqué) que la tâche se termine. Mais la tâche ne peut pas se terminer, car elle attend que le thread d'interface utilisateur soit disponible. Impasse.

Il existe des moyens pour éviter cette impasse, mais ils sont tous une mauvaise idée. Par souci d'exhaustivité, les éléments suivants peuvent fonctionner:

Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

C'est une mauvaise idée, car vous bloquez toujours votre thread d'interface utilisateur en attente et ne faites rien d'utile.

Quelle est donc la solution? Allez asynchroniser complètement. L'appelant d'origine sur le thread d'interface utilisateur est probablement un gestionnaire d'événements, alors assurez-vous que c'est asynchrone.

63

vous pouvez utiliser return ValidateRequestAsync (userName, password) .GetAwaiter (). GetResult ();

5
savagepanda