J'ai un appel que je passe depuis l'intérieur d'une C#
application métro basée sur xaml sur le Win8 CP; cet appel atteint simplement un service Web et renvoie des données JSON.
HttpMessageHandler handler = new HttpClientHandler();
HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");
var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);
Il se bloque à la await
mais l' appel http revient en fait presque immédiatement (confirmé par Fiddler); c'est comme si le await
était ignoré et qu'il s'y accrochait.
Avant de demander - OUI - la capacité de réseau privé est activée.
Des idées pourquoi cela se bloquerait?
c#
asynchronous
async-await
dotnet-httpclient
keithwarren7
la source
la source
async
méthode? Cela ne lève-t-il pas une exception?Réponses:
Découvrez cette réponse à ma question qui semble être très similaire.
Quelque chose à essayer: appelez
ConfigureAwait(false)
la tâche renvoyée parGetStreamAsync()
. Par exempleQue cela soit utile ou non dépend de la façon dont votre code ci-dessus est appelé - dans mon cas, l'appel de la
async
méthode utilisant aTask.GetAwaiter().GetResult()
provoqué le blocage du code.Cela est dû au fait que
GetResult()
bloque le thread actuel jusqu'à ce que la tâche se termine. Lorsque la tâche est terminée, elle tente de rentrer dans le contexte de thread dans lequel elle a été démarrée mais ne peut pas car il y a déjà un thread dans ce contexte, qui est bloqué par l'appel àGetResult()
... deadlock!Cet article MSDN donne quelques détails sur la façon dont .NET synchronise les threads parallèles - et la réponse donnée à ma propre question donne quelques bonnes pratiques.
la source
Juste un avertissement - si vous manquez l'attente au niveau supérieur dans un contrôleur ASP.NET et que vous renvoyez la tâche au lieu du résultat en tant que réponse, elle se bloque en fait dans le ou les appels d'attente imbriqués sans erreur. Une erreur stupide, mais si j'avais vu ce post, cela m'aurait peut-être fait gagner du temps en vérifiant le code pour quelque chose d'étrange.
la source
Avertissement: je n'aime pas la solution ConfigureAwait () car je la trouve non intuitive et difficile à retenir. Au lieu de cela, je suis arrivé à la conclusion d'envelopper les appels de méthode non attendus dans Task.Run (() => myAsyncMethodNotUsingAwait ()). Cela semble fonctionner à 100% mais pourrait être juste une condition de course !? Je ne sais pas trop ce qui se passe pour être honnête. Cette conclusion pourrait être fausse et je risque mes points StackOverflow ici pour apprendre, espérons-le, des commentaires :-P. Veuillez les lire!
Je viens d'avoir le problème décrit et j'ai trouvé plus d'informations ici .
La déclaration est: "vous ne pouvez pas appeler une méthode asynchrone"
d'une méthode qui bloque
Dans mon cas, je ne pouvais pas changer la méthode d'appel et ce n'était pas asynchrone. Mais je ne me souciais pas vraiment du résultat. Si je me souviens bien, cela ne fonctionnait pas non plus en supprimant le .Result et en manquant l'attente.
Alors j'ai fait ceci:
Dans mon cas, je ne me souciais pas du résultat de la méthode d'appel non asynchrone, mais je suppose que c'est assez courant dans ce cas d'utilisation. Vous pouvez utiliser le résultat dans la méthode asynchrone appelante.
la source