Je manque peut-être 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); }
Il se peut que je manque quelque chose
Tu es.
Quelle est la différence entre faire
Task.Wait
etawait task
?
Vous commandez votre déjeuner du serveur au restaurant. Un moment après avoir donné votre commande, un ami entre 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 soit terminée – vous pouvez attendre que votre soupe arrive et ne rien faire 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
bloque jusqu’à ce que la tâche soit terminée – vous ignorez votre ami jusqu’à ce que la tâche soit terminée. await
continue à traiter les messages dans la queue des messages et, lorsque la tâche est terminée, elle met en queue un message indiquant “ramasser là où vous l’avez laissé après cette attente”. Vous parlez à votre ami et quand il y a une pause dans la conversation, la soupe arrive.
Pour démontrer la réponse d’Eric, voici un code:
public void ButtonClick(object sender, EventArgs e) { Task t = new Task.Factory.StartNew(DoSomethingThatTakesTime); t.Wait(); //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! UpdateLabelToSayItsComplete(); } public async void ButtonClick(object sender, EventArgs e) { var result = Task.Factory.StartNew(DoSomethingThatTakesTime); await result; //If you press Button2 now you will see stuff in the console and //when the long method returns it will update the label! UpdateLabelToSayItsComplete(); } public void Button_2_Click(object sender, EventArgs e) { Console.WriteLine("Button 2 Clicked"); } private void DoSomethingThatTakesTime() { Thread.Sleep(10000); }
Cet exemple montre très clairement la différence. Avec async / waiting, le thread appelant ne sera pas bloqué et continuera à s’exécuter.
static void Main(ssortingng[] args) { WriteOutput("Program Begin"); // DoAsTask(); DoAsAsync(); WriteOutput("Program End"); Console.ReadLine(); } static void DoAsTask() { WriteOutput("1 - Starting"); var t = Task.Factory.StartNew(DoSomethingThatTakesTime); WriteOutput("2 - Task started"); t.Wait(); WriteOutput("3 - Task completed with result: " + t.Result); } static async Task DoAsAsync() { WriteOutput("1 - Starting"); var t = Task.Factory.StartNew (DoSomethingThatTakesTime); WriteOutput("2 - Task started"); var result = await t; WriteOutput("3 - Task completed with result: " + result); } static int DoSomethingThatTakesTime() { WriteOutput("A - Started something"); Thread.Sleep(1000); WriteOutput("B - Completed something"); return 123; } static void WriteOutput(ssortingng message) { Console.WriteLine("[{0}] {1}", Thread.CurrentThread.ManagedThreadId, message); }
Sortie DoAsTask:
[1] Début du programme [1] 1 - Commencer [1] 2 - Tâche lancée [3] A - Commencé quelque chose [3] B - quelque chose complété [1] 3 - Tâche terminée avec résultat: 123 [1] Fin du programme
Sortie DoAsAsync:
[1] Début du programme [1] 1 - À partir de [1] 2 - Tâche lancée [3] A - Commencé quelque chose [1] Fin du programme [3] B - quelque chose complété [3] 3 - Tâche terminée avec résultat: 123
Mise à jour: Exemple amélioré en affichant l’ID de thread dans la sortie.
Dans cet exemple, pas beaucoup, pratiquement. Si vous attendez une tâche renvoyée sur un thread différent (comme un appel WCF) ou renoncez au contrôle du système d’exploitation (comme File IO), attendez-vous à utiliser moins de ressources système en ne bloquant pas un thread.
Wait () provoquera l’exécution de code potentiellement asynchrone de manière synchronisée. attendre ne sera pas.
Par exemple, vous avez une application Web asp.net. UserA appels / getUser / 1 noeud final. asp.net app pool choisira un thread à partir du pool de threads (Thread1) et que ce thread effectuera un appel http. Si vous attendez (), ce thread sera bloqué jusqu’à ce que l’appel HTTP soit résolu. Pendant qu’il attend, si UserB appelle / getUser / 2, le pool d’applications devra servir un autre thread (Thread2) pour effectuer un nouvel appel http. Vous venez de créer (bien, extrait du pool d’applications en fait) un autre thread sans raison, car vous ne pouvez pas utiliser Thread1, il était bloqué par Wait ().
Si vous utilisez wait sur Thread1, SyncContext gérera la synchronisation entre Thread1 et http. Simplement, il notifiera une fois l’appel http terminé. Pendant ce temps, si UserB appelle / getUser / 2, vous utiliserez à nouveau Thread1 pour effectuer un appel http, car il a été libéré une fois que l’attente a été touchée. Ensuite, une autre demande peut l’utiliser encore plus. Une fois l’appel HTTP terminé (user1 ou user2), Thread1 peut obtenir le résultat et retourner à l’appelant (client). Thread1 a été utilisé pour plusieurs tâches.
Dans l’exemple ci-dessus, vous pouvez utiliser “TaskCreationOptions.HideScheduler” et modifier considérablement la méthode “DoAsTask”. La méthode elle-même n’est pas asynchrone, comme cela se produit avec “DoAsAsync” car elle retourne une valeur “Task” et est marquée comme “async”, créant plusieurs combinaisons. :
static Task DoAsTask() { WriteOutput("1 - Starting"); var t = Task.Factory.StartNew(DoSomethingThatTakesTime, TaskCreationOptions.HideScheduler); //<-- HideScheduler do the magic TaskCompletionSource tsc = new TaskCompletionSource (); t.ContinueWith(tsk => tsc.TrySetResult(tsk.Result)); //<-- Set the result to the created Task WriteOutput("2 - Task started"); tsc.Task.ContinueWith(tsk => WriteOutput("3 - Task completed with result: " + tsk.Result)); //<-- Complete the Task return tsc.Task; }