J’ai cherché les différences entre 2 paires ci-dessus, mais je n’ai trouvé aucun article expliquant clairement à ce sujet, ni quand utiliser l’un ou l’autre.
Alors, quelle est la différence entre SaveChanges()
et SaveChangesAsync()
?
Et entre Find()
et FindAsync()
?
Côté serveur, lorsque nous utilisons des méthodes Async
, nous devons également append Ainsi, je ne pense pas que ce soit asynchrone côté serveur.
Cela vous aide-t-il uniquement à empêcher le blocage de l’interface utilisateur sur le navigateur côté client? Ou y at-il des avantages et des inconvénients entre eux?
Chaque fois que vous devez effectuer une action sur un serveur distant, votre programme génère la demande, l’envoie, puis attend une réponse. Je vais utiliser SaveChanges()
et SaveChangesAsync()
comme exemple, mais il en va de même pour Find()
et FindAsync()
.
Disons que vous avez une liste myList
de plus de 100 éléments que vous devez append à votre firebase database. Pour insérer cela, votre fonction ressemblerait à quelque chose comme ceci:
using(var context = new MyEDM()) { context.MyTable.AddRange(myList); context.SaveChanges(); }
Tout d’abord, vous créez et MyEDM
, ajoutez la liste myList
à la table MyTable
, puis appelez SaveChanges()
pour conserver les modifications apscopes à la firebase database. Cela fonctionne comme vous voulez, les enregistrements sont validés, mais votre programme ne peut rien faire avant que la validation ne soit terminée. Cela peut prendre beaucoup de temps en fonction de ce que vous commettez. Si vous apportez des modifications aux enregistrements, l’entité doit les valider un par un (une fois, j’ai économisé 2 minutes pour les mises à jour)!
Pour résoudre ce problème, vous pouvez faire l’une des deux choses suivantes: Le premier est que vous pouvez démarrer un nouveau thread pour gérer l’insertion. Bien que cela libère le thread appelant pour continuer à exécuter, vous avez créé un nouveau thread qui va juste restr là et attendre. Il n’y a pas besoin de cette surcharge, et c’est ce que les async await
modèle de résolution.
Pour les opérations d’E / S, await
vite pour devenir votre meilleur ami. En prenant la section de code ci-dessus, nous pouvons la modifier pour être:
using(var context = new MyEDM()) { Console.WriteLine("Save Starting"); context.MyTable.AddRange(myList); await context.SaveChangesAsync(); Console.WriteLine("Save Complete"); }
C’est un tout petit changement, mais il y a des effets profonds sur l’efficacité et la performance de votre code. Alors que se passe-t-il? Le début du code est le même, vous créez une instance de MyEDM
et ajoutez votre myList
à MyTable
. Mais lorsque vous appelez await context.SaveChangesAsync()
, l’exécution du code retourne à la fonction appelante! Ainsi, pendant que vous attendez que tous ces enregistrements soient validés, votre code peut continuer à s’exécuter. Supposons que la fonction qui contenait le code ci-dessus avait la signature de public async Task SaveRecords(List
, la fonction appelante pourrait ressembler à ceci:
public async Task MyCallingFunction() { Console.WriteLine("Function Starting"); Task saveTask = SaveRecords(GenerateNewRecords()); for(int i = 0; i < 1000; i++){ Console.WriteLine("Continuing to execute!"); } await saveTask; Console.Log("Function Complete"); }
Pourquoi vous auriez une fonction comme celle-ci, je ne sais pas, mais ce qu'elle affiche montre comment async await
travaux. Commençons d'abord par ce qui se passe.
L'exécution entre la fonction MyCallingFunction
, Function Starting
moment, Save Starting
est écrit sur la console, puis la fonction SaveChangesAsync()
est appelée. A ce stade, l'exécution retourne à MyCallingFunction
et entre dans la boucle for en écrivant «Continuing to Execute» jusqu'à 1000 fois. Lorsque SaveChangesAsync()
finit, l'exécution retourne à la fonction SaveRecords
écrivant Save Complete
sur la console. Une fois que tout dans SaveRecords
terminé, l'exécution continue dans MyCallingFunction
à MyCallingFunction
que SaveChangesAsync()
termine. Confus? Voici un exemple de sortie:
Fonction de démarrage Enregistrer à partir de Continuer à exécuter! Continuer à exécuter! Continuer à exécuter! Continuer à exécuter! Continuer à exécuter! .... Continuer à exécuter! Sauver Complete! Continuer à exécuter! Continuer à exécuter! Continuer à exécuter! .... Continuer à exécuter! Fonction complète!
Ou peut-être:
Fonction de démarrage Enregistrer à partir de Continuer à exécuter! Continuer à exécuter! Sauver Complete! Continuer à exécuter! Continuer à exécuter! Continuer à exécuter! .... Continuer à exécuter! Fonction complète!
C'est la beauté de l' async await
, votre code peut continuer à fonctionner pendant que vous attendez que quelque chose se termine. En réalité, vous auriez une fonction similaire à celle de votre fonction d'appel:
public async Task MyCallingFunction() { List myTasks = new List (); myTasks.Add(SaveRecords(GenerateNewRecords())); myTasks.Add(SaveRecords2(GenerateNewRecords2())); myTasks.Add(SaveRecords3(GenerateNewRecords3())); myTasks.Add(SaveRecords4(GenerateNewRecords4())); await Task.WhenAll(myTasks.ToArray()); }
Ici, vous avez quatre fonctions d'enregistrement de sauvegarde différentes en même temps . MyCallingFunction
se terminera beaucoup plus rapidement en utilisant async await
si les fonctions individuelles de SaveRecords
ont été appelées en série.
La seule chose que je n'ai pas encore abordée est le mot-clé await
. Cela empêche la fonction actuelle de s'exécuter jusqu'à ce que la Task
soit terminée. Ainsi, dans le cas de la fonction MyCallingFunction
origine, la ligne Function Complete
ne sera pas écrite dans la console tant que la fonction SaveRecords
ne sera pas terminée.
En bref, si vous avez une option pour utiliser async await
, vous devriez, car cela va grandement améliorer les performances de votre application.
Cette déclaration est incorrecte:
Côté serveur, lorsque nous utilisons des méthodes Async, nous devons également append
Vous n’avez pas besoin d’append “wait”. “wait” est simplement un mot clé pratique en C # qui vous permet d’écrire plus de lignes de code après l’appel, et ces autres lignes ne seront exécutées qu’à la fin de l’opération de sauvegarde. Mais comme vous l’avez souligné, vous pouvez accomplir cela simplement en appelant SaveChanges au lieu de SaveChangesAsync.
Mais fondamentalement, un appel asynchrone est beaucoup plus que cela. L’idée ici est que si vous pouvez faire d’autres tâches (sur le serveur) pendant que l’opération de sauvegarde est en cours, vous devez utiliser SaveChangesAsync. Ne pas utiliser “attendre”. Appelez simplement SaveChangesAsync, puis continuez à faire d’autres choses en parallèle. Cela inclut potentiellement, dans une application Web, le retour d’une réponse au client avant même que la sauvegarde soit terminée. Mais bien sûr, vous voudrez toujours vérifier le résultat final de la sauvegarde afin que, en cas d’échec, vous puissiez le communiquer à votre utilisateur ou le connecter d’une manière ou d’une autre.