Quelle est la différence entre la Tâche.Start/Wait et Async/Await?
J'ai peut-être raté quelque chose mais quelle est la différence entre faire:
public void MyMethod()
{
Task t = Task.Factory.StartNew(DoSomethingThatTakesTime);
t.Wait();
UpdateLabelToSayItsComplete();
}
public async void MyMethod()
{
var result = Task.Factory.StartNew(DoSomethingThatTakesTime);
await result;
UpdateLabelToSayItsComplete();
}
private void DoSomethingThatTakesTime()
{
Thread.Sleep(10000);
}
Vous devez vous connecter pour publier un commentaire.
Vous.
Vous commandez votre repas à partir du serveur au restaurant. Un moment après votre commande, un ami arrive et s'assoit à côté de vous et commence une conversation. Maintenant, vous avez deux choix. Vous pouvez ignorer votre ami jusqu'à ce que la tâche est terminée: vous pouvez attendre jusqu'à ce que votre soupe arrive et ne rien faire d'autre pendant que vous attendez. Ou vous pouvez répondre à votre ami, et lorsque votre ami arrête de parler, le serveur vous apportera votre soupe.
Task.Wait
blocs jusqu'à ce que la tâche est terminée -- vous ignorez votre ami jusqu'à ce que la tâche est terminée.await
conserve traitement des messages dans la file d'attente de messages, et lorsque la tâche est terminée, il place en file d'attente un message qui dit "reprendre là où vous l'avez laissé après qui l'attendent". Vous parlez à votre ami, et quand il y a une pause dans la conversation, la soupe arrive.Task.Wait
une coopérative de bloc? c'est à dire qu'il ne va pas bloquer le thread il suffit de choisir une autre tâche de la piscine et de l'exécuter que si le délai d'attente est toujours actif.Task
qui prend 10 ms aurait fait exécuter une 10 de l'heureTask
sur votre fil, ainsi le blocage de vous pour l'ensemble de 10 heures?Task.Wait
. Vous auriez à n'utiliser que si vous devez absolument le bloc jusqu'à ce que la tâche est terminée, et vous savez qu'il ne va pas à l'impasse si vous le faites.SynchronizationContext
. Par exemple,WindowsFormsSynchronizationContext
exécute les messages dans la boucle de message un par un. En attente sur le thread d'INTERFACE utilisateur signifie simplement sauter au message suivant dans la boucle de message.async-await
ne peut que l'aider si l'opération est IO base; pas le processeur de la faim. Pourquoi donc? Si je lance en mode synchrone, mon programme tout au long de l'exécution utilise 10% de CPU. Si je casse mon programme en 2 petits morceaux et exécuter les morceaux de manière asynchrone, il faut terminer l'exécution de la mi-temps avec 20% d'utilisation du PROCESSEUR. Veuillez expliquer si je suis encore miss-comprendre quelque chose.À démontrer Eric réponse est ici un peu de code:
//If you press Button2 now you won't see anything in the console until this task is complete and then the label will be updated!
" est trompeur. En appuyant sur le bouton avect.Wait();
dans l'événement clic du bouton gestionnaire deButtonClick()
il n'est pas possible d'appuyer sur quoi que ce soit et puis voir quelque chose dans la console et mise à jour de l'étiquette "jusqu'à ce que cette tâche est terminée" depuis l'interface graphique est bloqué et ne répond pas, c'est tous les clics ou les interactions avec les GUI sont PERDU jusqu'à l'achèvement de la tâche en attentet.Wait
va bloquer le thread principal jusqu'à ce que la tâche est terminée."Cet exemple illustre la différence très clairement. Avec async/await le thread appelant ne va pas bloquer et de poursuivre l'exécution.
DoAsTask De Sortie:
DoAsAsync De Sortie:
Mise à jour: Amélioration de l'exemple en montrant l'ID de thread dans la sortie.
Wait(), va entraîner à exécuter potentiellement async code de la synchronisation de la manière. attendent le seront pas.
Par exemple, vous avez une asp.net application web. UserA appels /getUser/1 point de terminaison. asp.net application de la piscine va chercher un thread du pool de thread (Thread1) et, ce thread va faire un appel http. Si vous n'Wait(), ce fil sera bloqué jusqu'à ce http appel résout. Alors qu'il est en attente, si UserB appels /getUser/2, alors, app piscine aurez besoin pour servir un autre thread (Thread2) de faire appel http de nouveau. Vous venez de créer (Bien, extraite de l'application de la piscine, en fait) un autre thread pour aucune raison, parce que vous ne pouvez pas utiliser Thread1 il a été bloqué par Wait().
Si vous utilisez attendent sur Thread1, puis, SyncContext va gérer la synchronisation entre Thread1 et http appel. Simplement, il devra en aviser une fois que http appel est fait. En attendant, si UserB appels /getUser/2, alors, vous allez utiliser Thread1 de nouveau à faire appel http, parce qu'il a été libéré une fois qu'attendent a été touché. Puis une autre demande peut l'utiliser, même plus encore. Une fois http appel est fait (user1 ou user2), Thread1 pouvez obtenir le résultat et le retour à l'appelant (client). Thread1 a été utilisé pour plusieurs tâches.
Dans cet exemple, pas beaucoup, pratiquement. Si vous êtes en attente d'une Tâche qui renvoie sur un autre thread (comme un WCF appel) ou la cessation de contrôle au système d'exploitation (comme les e /s de Fichier), vous attendent utilisera moins de ressources système pas de blocage à un fil.
Dans l'exemple ci-dessus, vous pouvez utiliser "TaskCreationOptions.HideScheduler", et grandement modifier l' "DoAsTask" la méthode. La méthode elle-même n'est pas asynchrone, comme il arrive avec "DoAsAsync" parce qu'il renvoie à une "Tâche" de la valeur et est marqué comme "async", faisant plusieurs combinaisons, c'est la façon dont il me donne exactement le même que l'utilisation de "async /await":