Ce qui se passe lors de l'attente sur une Tâche de Résultat?
Je suis en utilisant le HttpClient pour publier des données à un service distant dans un .NET 4.0 projet. Je ne suis pas concerné par cette opération de blocage, alors j'ai pensé que je ne pouvais l'ignorer ContinueWith ou async/await et l'utilisation de Résultat.
Pendant le débogage, j'ai couru dans un problème où le serveur distant n'était pas sensible. Comme je passais à travers le code, il semblait que mon code est juste arrêté en cours d'exécution sur la troisième ligne... le pointeur de pile actuel de la ligne a cessé d'être surligné en jaune, et n'ont pas de passer à la ligne suivante. Il a tout simplement disparu. Il m'a fallu un certain temps pour réaliser que je devrais attendre la demande de délai d'attente.
var client = new HttpClient();
var task = client.PostAsync("http://someservice/", someContent);
var response = task.Result;
Ma compréhension était que l'appel de Résultat sur la Tâche causé le code à exécuter de manière synchrone, à se comporter plus comme ça (je sais il n'y a pas de méthode Post dans la HttpClient):
var client = new HttpClient();
var response = client.Post("http://someservice/", someContent);
Je ne suis pas sûr que ce soit une mauvaise chose, je suis juste essayer d'obtenir ma tête autour de lui. Est-il vrai que, en vertu du fait que la HttpClient est de retour Tâches au lieu de directement les résultats, ma demande est automatiquement profitant de l'asynchronie même quand je pense que je vais l'éviter?
- la doc dit: "L'accesseur get pour cette propriété garantit que l'opération asynchrone est terminée avant de revenir." de sorte que vous serait correct en supposant que. Cependant, peut-être que vous exécutez dans le cas où la Tâche déclenche une exception parce que l'opération a échoué.
- Je suppose que ce que m'a jeté a été que le pointeur de pile disparu. Je ne savais pas que si j'ai attendu assez longtemps, le blocage de Suite appel exception. Il a juste regardé comme si le code de l'arrêté d'exécution de la moitié du chemin par le biais de la méthode. Peut-être cela devrait être une VS Connectez type de question de demander de l'INTERFACE utilisateur de repère qu'il y est une opération asynchrone en attente sur la troisième ligne. Je pense que le débogueur même m'a ramené à l'appel de la classe.
- toute solution finale avec l'intégralité du code source?
Vous devez vous connecter pour publier un commentaire.
Dans Windows, toutes les e/S asynchrones. Synchrone Api sont juste une abstraction pratique.
Donc, lorsque vous utilisez
HttpWebRequest.GetResponse
, ce qui se passe réellement est le I/O est démarré (de manière asynchrone), et le thread appelant (de façon synchrone) se bloque, en attendant qu'il termine.De même, lorsque vous utilisez
HttpClient.PostAsync(..).Result
, le I/O est démarré (de manière asynchrone), et le thread appelant (de façon synchrone) se bloque, en attendant qu'il termine.Je recommande généralement les gens utilisent
await
plutôt queTask.Result
ouTask.Wait
pour les raisons suivantes:Task
qui est le résultat d'uneasync
méthode, vous pouvez facilement entrer dans une situation de blocage.Task.Result
etTask.Wait
envelopper toutes les exceptions dans unAggregateException
(parce que ces Api sont des rescapés de la TPL). Donc, les erreurs de manipulation est plus complexe.Toutefois, si vous êtes conscients de ces limitations, il y a certaines situations où le blocage sur un
Task
peut être utile (par exemple, dans une application de Console deMain
).Task.Run
.Capturer le résultat d'une tâche bloque le thread courant. Il n'y a pas de point à l'aide d'une version asynchrone de la méthode dans ce cas.
Post()
etPostAsync().Result
permettra à la fois de bloquer.Si vous souhaitez faire usage de la simultanéité, vous devez écrire en tant que tel:
Depuis
PostContent()
lui-même renvoie à une Tâche, l'appel de méthode, il devrait également vous attendent.Par exemple, si vous appelez
ProcessResult()
en un clic sur un bouton gestionnaire, vous verrez que l'INTERFACE utilisateur est toujours réactive, d'autres contrôles fonctionnent toujours.