Dans ASP.NET HttpClient.GetAsync(...)
des blocages occasionnels se produisent lors de l'utilisation de await
/async
Lors de l'utilisation des nouvelles fonctionnalités du langage async
/await
et de l'API Tasks dans .NET 4.5, les résultats « en attente » de httpClient.GetAsync(...)
peuvent parfois rester bloqués. Cela est dû à une mauvaise utilisation de l'API.
Explication
Dans ASP.NET, un seul thread peut gérer une requête à la fois. Un traitement parallèle peut être effectué si vous le souhaitez, mais des threads supplémentaires devront être empruntés au pool de threads et ces threads n'auront aucun contexte de requête. Ceci est géré par ASP.NET SynchronizationContext.
Par défaut, lors de l'attente d'une tâche, les méthodes reprennent sur le SynchronizationContext capturé ou le TaskScheduler capturé (s'il n'y a pas de SynchronizationContext). Normalement, c'est l'idéal : l'action du contrôleur asynchrone attendra quelque chose, et lorsqu'elle reprendra, elle reprendra en utilisant le contexte de requête.
Test5Controller.Get
Cette méthode de contrôleur particulière exécute AsyncAwait_GetSomeDataAsync (dans le contexte d'une requête ASP.NET). AsyncAwait_GetSomeDataAsync exécute HttpClient.GetAsync (dans le contexte d'une requête ASP.NET). La requête HTTP est envoyée et HttpClient.GetAsync renvoie une tâche inachevée. Ensuite, AsyncAwait_GetSomeDataAsync attend la tâche inachevée et renvoie donc une tâche inachevée. Désormais, Test5Controller.Get bloque le thread actuel jusqu'à la fin de la tâche.
La réponse HTTP arrive et la tâche renvoyée par HttpClient.GetAsync est terminée. AsyncAwait_GetSomeDataAsync tente ensuite de reprendre dans le contexte de requête ASP.NET. Cependant, il existe déjà un thread dans ce contexte : le thread bloqué dans Test5Controller.Get. Cela peut conduire à une impasse.
Bonnes pratiques
Pour corriger ce problème, il est recommandé :
ConfigureAwait(false)
dans les méthodes asynchrones de votre "bibliothèque" autant que possible. Dans ce cas, AsyncAwait_GetSomeDataAsync sera remplacé par result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
await
au lieu de "GetResult" (Task.Result
, Task.Wait
doit également être remplacé par await
). En suivant ces bonnes pratiques, la suite (le reste de la méthode AsyncAwait_GetSomeDataAsync) s'exécutera sur un thread de pool de threads normal sans avoir besoin d'entrer dans le contexte de requête ASP.NET, et le contrôleur lui-même est asynchrone (ne bloquera pas le fil de demande) .
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!