D'après ma compréhension, l'une des principales choses à faire async
et àawait
faire est de rendre le code facile à écrire et à lire - mais les utilise-t-il comme des threads d'arrière-plan pour générer une logique de longue durée?
J'essaie actuellement l'exemple le plus basique. J'ai ajouté quelques commentaires en ligne. Pouvez-vous le clarifier pour moi?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
c#
.net
asynchronous
async-await
Dan Dinu
la source
la source
Réponses:
Lors de l'utilisation
async
etawait
le compilateur génère une machine d'état en arrière-plan.Voici un exemple sur lequel j'espère pouvoir expliquer certains des détails de haut niveau qui se déroulent:
OK, alors qu'est-ce qui se passe ici:
Task<int> longRunningTask = LongRunningOperationAsync();
commence à exécuterLongRunningOperation
Un travail indépendant est effectué sur supposons que le thread principal (Thread ID = 1)
await longRunningTask
est alors atteint.Maintenant, si le
longRunningTask
n'est pas terminé et qu'il est toujours en cours d'exécution,MyMethodAsync()
reviendra à sa méthode d'appel, donc le thread principal ne sera pas bloqué. Une fois l'opérationlongRunningTask
terminée, un thread du ThreadPool (peut être n'importe quel thread) reviendraMyMethodAsync()
dans son contexte précédent et poursuivra l'exécution (dans ce cas, l'impression du résultat sur la console).Un deuxième cas serait que le
longRunningTask
a déjà terminé son exécution et que le résultat est disponible. En atteignant le,await longRunningTask
nous avons déjà le résultat, donc le code continuera à s'exécuter sur le même thread. (dans ce cas, impression du résultat sur la console). Bien sûr, ce n'est pas le cas pour l'exemple ci-dessus, où il y a unTask.Delay(1000)
impliqué.la source
Ils doivent rendre le code asynchrone facile à écrire et à lire, oui.
Pas du tout.
Le
async
mot clé active leawait
mot clé. Donc, toute méthode utilisantawait
doit être marquéeasync
.Non, car les
async
méthodes ne sont pas exécutées sur un autre thread par défaut.Non.
Vous pouvez trouver mon
async
/await
intro utile. Les documents MSDN officiels sont également exceptionnellement bons (en particulier la section TAP ), et l'async
équipe a publié une excellente FAQ .la source
async
méthodes ne sont pas exécutées sur un autre thread par défaut. Dans votre exemple, l'Sleep()
appel à l'intérieurDoSomethingAsync()
bloque le thread en cours, ce qui empêche l'exécution de se poursuivre à l'intérieurbutton1_Click()
jusqu'à laDoSomethingAsync()
fin. Notez que tandis queThread.Sleep()
bloque le thread d'exécution,Task.Delay() does not.
Explication
Voici un rapide exemple de
async
/await
à un niveau élevé. Il y a beaucoup plus de détails à considérer au-delà de cela.Remarque:
Task.Delay(1000)
simule le travail pendant 1 seconde. Je pense qu'il vaut mieux penser à cela comme attendant une réponse d'une ressource externe. Puisque notre code attend une réponse, le système peut mettre la tâche en cours de côté et y revenir une fois terminée. En attendant, il peut faire un autre travail sur ce fil.Dans l'exemple ci-dessous, le premier bloc fait exactement cela. Il démarre immédiatement toutes les tâches (les
Task.Delay
lignes) et les met de côté. Le code s'arrêtera sur laawait a
ligne jusqu'à ce que le délai de 1 seconde soit effectué avant de passer à la ligne suivante. Depuisb
,c
,d
ete
tout a commencé l' exécution presque exactement en même temps quea
( en raison du manque de await), ils devraient terminer à peu près en même temps dans ce cas.Dans l'exemple ci-dessous, le deuxième bloc démarre une tâche et attend qu'elle se termine (c'est ce qui se
await
passe) avant de démarrer les tâches suivantes. Chaque itération prend 1 seconde. leawait
met le programme en pause et attend le résultat avant de continuer. Il s'agit de la principale différence entre les premier et deuxième blocs.Exemple
PRODUCTION:
Informations supplémentaires concernant SynchronizationContext
Remarque: C'est là que les choses deviennent un peu brumeuses pour moi, donc si je me trompe, corrigez-moi et je mettrai à jour la réponse. Il est important d'avoir une compréhension de base de la façon dont cela fonctionne, mais vous pouvez vous en tirer sans être un expert tant que vous n'utilisez jamais
ConfigureAwait(false)
, même si vous perdrez probablement une opportunité d'optimisation, je suppose.Il y a un aspect de cela qui rend le concept
async
/await
quelque peu plus difficile à saisir. C'est le fait que dans cet exemple, tout cela se passe sur le même thread (ou du moins ce qui semble être le même thread en ce qui concerne sonSynchronizationContext
). Par défaut,await
restaurera le contexte de synchronisation du thread d'origine sur lequel il s'exécutait. Par exemple, dans ASP.NET, vous en avez unHttpContext
qui est lié à un thread lorsqu'une demande arrive. Ce contexte contient des éléments spécifiques à la demande Http d'origine, tels que l'objet de demande d'origine qui contient des éléments tels que la langue, l'adresse IP, les en-têtes, etc. . Si vous changez de threads à mi-chemin du traitement de quelque chose, vous pourriez éventuellement essayer d'extraire des informations de cet objet sur un autreHttpContext
ce qui pourrait être désastreux. Si vous savez que vous n'utiliserez le contexte pour rien, vous pouvez choisir de "ne pas vous en soucier". Cela permet essentiellement à votre code de s'exécuter sur un thread séparé sans apporter le contexte avec lui.Comment y parvenez-vous? Par défaut, le
await a;
code fait en réalité l'hypothèse que vous voulez capturer et restaurer le contexte:Si vous souhaitez autoriser le code principal à continuer sur un nouveau thread sans le contexte d'origine, vous utilisez simplement false au lieu de true pour qu'il sache qu'il n'a pas besoin de restaurer le contexte.
Une fois le programme en pause, il continuera potentiellement sur un thread entièrement différent avec un contexte différent. C'est de là que viendrait l'amélioration des performances - elle pourrait continuer sur n'importe quel thread disponible sans avoir à restaurer le contexte d'origine avec lequel elle a commencé.
Est-ce que c'est compliqué? Enfer ouais! Pouvez-vous le comprendre? Probablement! Une fois que vous avez compris les concepts, passez aux explications de Stephen Cleary qui tendent à être davantage orientées vers quelqu'un ayant une compréhension technique de
async
/await
déjà.la source
await MethodCall()
un gaspillage absolu? Vous pourriez aussi bien laisser tomber leawait
/async
?await
, je pense qu'il libère le fil dans la piscine au lieu de le maintenir. Cela le rend disponible pour une utilisation ailleurs en attendant le retour de la tâcheSuite aux autres réponses, jetez un œil à l' attente (Référence C #)
et plus précisément à l'exemple inclus, cela explique un peu votre situation
la source
Task.Delay
incendies.Affichage des explications ci-dessus en action dans un programme de console simple:
Et la sortie est:
Donc,
TestAsyncAwaitMethods
. Cela revient immédiatement sans arrêter le thread actuel et nous voyons immédiatement le message `` Appuyez sur n'importe quelle touche pour quitter ''LongRunningMethod
tourne en arrière-plan. Une fois terminé, un autre thread de Threadpool reprend ce contexte et affiche le message finalAinsi, aucun thread n'est bloqué.
la source
return 1
partie mérite une explication supplémentaire: leawait
mot - clé vous permet de retournerTask<T>
directement le type sous-jacent , ce qui facilite l'adaptation de votre code sortant au monde en attente / asynchrone . Mais vous n'êtes pas obligé de renvoyer une valeur, car il est possible de retourner unTask
sans spécifier de type de retour, ce qui serait l'équivalent d'unevoid
méthode synchrone . Gardez à l'esprit que C # autorise lesasync void
méthodes, mais vous devez éviter de le faire à moins que vous ne vous attaquiez aux gestionnaires d'événements.Je pense que vous avez choisi un mauvais exemple avec
System.Threading.Thread.Sleep
Le point d'une
async
tâche est de la laisser s'exécuter en arrière-plan sans verrouiller le thread principal, comme faire unDownloadFileAsync
System.Threading.Thread.Sleep
n'est pas quelque chose qui "se fait", il dort juste, et donc votre prochaine ligne est atteinte après 5 secondes ...Lisez cet article, je pense que c'est une excellente explication
async
etawait
concept: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspxla source
Thread.Sleep
bloque le thread (le thread ne peut rien faire d'autre que rester inactif), mais pas une méthode asynchrone. Dans le cas deDownloadFileAsync
, le thread peut aller faire autre chose jusqu'à ce qu'une réponse vienne du serveur distant. Un meilleur espace réservé pour «une tâche qui prend du temps» dans une méthode asynchrone estTask.Delay
, car il s'agit en fait d'asynchrone.async
mot - clé. Mais sa méthode fonctionnait toujours de manière synchrone, et cette réponse expliquait parfaitement pourquoi: parce qu'il n'avait en fait exécuté aucun code asynchrone. Les méthodes marquéesasync
fonctionnent toujours de manière synchrone jusqu'à ce que vous soyezawait
incompletTask
. S'il n'y en a pasawait
, la méthode s'exécute de manière synchrone et le compilateur vous en avertira.Voici un programme de console rapide pour le faire comprendre à ceux qui suivent. La
TaskToDo
méthode est votre méthode de longue durée que vous souhaitez rendre asynchrone. Le faire fonctionner async se fait par laTestAsync
méthode. La méthode des boucles de test exécute simplement lesTaskToDo
tâches et les exécute en mode asynchrone. Vous pouvez le voir dans les résultats, car ils ne se terminent pas dans le même ordre d'une exécution à l'autre - ils font rapport au thread de l'interface utilisateur de la console lorsqu'ils ont terminé. Simpliste, mais je pense que les exemples simplistes font mieux ressortir le cœur du modèle que les exemples plus impliqués:la source
Pour un apprentissage plus rapide ..
Comprendre le flux d'exécution de la méthode (avec un diagramme): 3 minutes
Introspection de la question (pour apprendre): 1 min
Passez rapidement à travers le sucre de syntaxe: 5 minutes
Partagez la confusion d'un développeur: 5 minutes
Problème: changez rapidement une implémentation réelle du code normal en code asynchrone: 2 minutes
Où ensuite?
Comprendre le flux d'exécution de la méthode (avec un diagramme): 3 minutes
Dans cette image, concentrez-vous sur # 6 (rien de plus)
À l'étape n ° 6: l'exécution s'est arrêtée ici car elle est à court de travail. Pour continuer, il a besoin d'un résultat de getStringTask (sorte de fonction). Par conséquent, il utilise un
await
opérateur pour suspendre sa progression et rendre le contrôle (rendement) à l'appelant (de cette méthode dans laquelle nous sommes). L'appel réel à getStringTask a été effectué plus tôt dans # 2. Au n ° 2, une promesse a été faite de renvoyer un résultat de chaîne. Mais quand rendra-t-il le résultat? Devrions-nous (# 1: AccessTheWebAsync) refaire un deuxième appel? Qui obtient le résultat, # 2 (instruction d'appel) ou # 6 (instruction en attente)L'appelant externe d'AccessTheWebAsync () attend également maintenant. Ainsi, l'appelant attend AccessTheWebAsync et AccessTheWebAsync attend GetStringAsync pour le moment. La chose intéressante est AccessTheWebAsync a fait un peu de travail avant d'attendre (# 4) peut-être pour gagner du temps. La même liberté de multitâche est également disponible pour l'appelant externe (et tous les appelants de la chaîne) et c'est le plus grand plus de ce truc 'async'! Vous avez l'impression que c'est synchrone ... ou normal mais ce n'est pas le cas.
Rappelez-vous, la méthode a déjà été retournée (# 2), elle ne peut pas revenir à nouveau (pas de deuxième fois). Alors, comment l'appelant saura-t-il? Il s'agit de tâches! La tâche a été réussie. La tâche était attendue (pas la méthode, pas la valeur). La valeur sera définie dans la tâche. Le statut de la tâche sera défini pour se terminer. L'appelant surveille simplement la tâche (# 6). Donc 6 # est la réponse à l'endroit où / qui obtient le résultat. Lectures supplémentaires pour plus tard ici .
Questionner l'introspection pour apprendre le plaisir: 1 min
Ajustons un peu la question:
Parce que l'apprentissage
Task
couvre automatiquement les deux autres (et répond à votre question)Passez rapidement à travers le sucre de syntaxe: 5 minutes
Avant la conversion (méthode originale)
internal static int Method(int arg0, int arg1) { int result = arg0 + arg1; IO(); // Do some long running IO. return result; }
une méthode Task-ified pour appeler la méthode ci-dessus
internal static Task<int> MethodTask(int arg0, int arg1) { Task<int> task = new Task<int>(() => Method(arg0, arg1)); task.Start(); // Hot task (started task) should always be returned. return task; }
Avons-nous mentionné attendre ou async? Non. Appelez la méthode ci-dessus et vous obtenez une tâche que vous pouvez surveiller. Vous savez déjà ce que la tâche renvoie .. un entier.
L'appel d'une tâche est légèrement délicat et c'est à ce moment que les mots clés commencent à apparaître. Appelons MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1) { int result = await HelperMethods.MethodTask(arg0, arg1); return result; }
Même code ci-dessus ajouté comme image ci-dessous:
await
async
(syntaxe obligatoire)Async
comme préfixe (norme de codage)await
est facile à comprendre mais les deux (async
,Async
) restants peuvent ne pas l'être :). Eh bien, il faut faire beaucoup plus de sens au compilateur though.Further lit pour plus tard iciPartagez la confusion d'un développeur: 5 minutes
Un développeur a fait une erreur de ne pas implémenter
Task
mais cela fonctionne toujours! Essayez de comprendre la question et juste la réponse acceptée fournie ici . J'espère que vous avez lu et bien compris. Le résumé est que nous ne pouvons pas voir / implémenter 'Task' mais il est implémenté quelque part dans une classe parent. De même, dans notre exemple, appeler un déjà construitMethodAsync()
est beaucoup plus facile que d'implémenter cette méthode avec unTask
(MethodTask()
) nous-mêmes. La plupart des développeurs ont du mal à se repérerTasks
lors de la conversion d'un code en code asynchrone.Conseil: essayez de trouver une implémentation Async existante (comme
MethodAsync
ouToListAsync
) pour sous-traiter la difficulté. Nous avons donc seulement besoin de traiter avec Async et d'attendre (ce qui est facile et assez similaire au code normal)Problème: changez rapidement une implémentation réelle du code normal en fonctionnement asynchrone: 2 minutes
La ligne de code indiquée ci-dessous dans Data Layer a commencé à se rompre (à de nombreux endroits). Parce que nous avons mis à jour une partie de notre code du framework .Net 4.2. * Vers le core .Net. Nous avons dû résoudre ce problème en 1 heure partout dans l'application!
peasy facile!
Async
etawait
.la ligne de code d'appel a changé comme ça
La signature de la méthode est passée de
Contract GetContract(int contractnumber)
à
async Task<Contract> GetContractAsync(int contractnumber)
la méthode d'appel a également été affectée: a
GetContractAsync(123456);
été appelée en tant queGetContractAsync(123456).Result;
Nous l'avons changé partout en 30 minutes!
Mais l'architecte nous a dit de ne pas utiliser la bibliothèque EntityFramework juste pour ça! Oops! drame! Ensuite, nous avons fait une implémentation de tâche personnalisée (yuk). Que vous savez comment. Toujours facile! ..encore yuk ..
Où ensuite? Il y a une merveilleuse vidéo rapide que nous pourrions regarder sur la conversion des appels synchrones en asynchrones dans ASP.Net Core , c'est peut-être probablement la direction que l'on prendrait après avoir lu ceci.
la source
Toutes les réponses ici utilisent
Task.Delay()
ou une autreasync
fonction intégrée. Mais voici mon exemple qui n'utilise aucune de cesasync
fonctions:la source
task.Wait();
et comment il peut être utilisé pour éviter l'async / attendre l'enfer: PCette réponse vise à fournir des informations spécifiques à ASP.NET.
En utilisant async / wait dans le contrôleur MVC, il est possible d'augmenter l'utilisation du pool de threads et d'obtenir un débit bien meilleur, comme expliqué dans l'article ci-dessous,
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
la source
Async & Attendre une explication simple
Analogie simple
Une personne peut attendre son train du matin. C'est tout ce qu'ils font car c'est leur tâche principale qu'ils effectuent actuellement. (programmation synchrone (ce que vous faites normalement!))
Une autre personne peut attendre son train du matin pendant qu'elle fume une cigarette, puis boire son café. (Programmation asynchrone)
Qu'est-ce que la programmation asynchrone?
La programmation asynchrone est l'endroit où un programmeur choisira d'exécuter une partie de son code sur un thread distinct du thread principal d'exécution, puis notifiera le thread principal à la fin.
Que fait réellement le mot-clé async?
Préfixe du mot-clé async à un nom de méthode comme
permet au programmeur d'utiliser le mot-clé wait lors de l'appel de tâches asynchrones. C'est tout.
Pourquoi est-ce important?
Dans de nombreux systèmes logiciels, le thread principal est réservé aux opérations spécifiquement liées à l'interface utilisateur. Si j'exécute un algorithme récursif très complexe qui prend 5 secondes pour se terminer sur mon ordinateur, mais je l'exécute sur le thread principal (thread d'interface utilisateur) Lorsque l'utilisateur essaie de cliquer sur quoi que ce soit sur mon application, il semblera être gelé car mon thread principal a été mis en file d'attente et traite actuellement beaucoup trop d'opérations. Par conséquent, le thread principal ne peut pas traiter le clic de souris pour exécuter la méthode à partir du clic de bouton.
Quand utilisez-vous Async et Await?
Utilisez les mots clés asynchrones idéalement lorsque vous faites quoi que ce soit qui n'implique pas l'interface utilisateur.
Disons donc que vous écrivez un programme qui permet à l'utilisateur de dessiner sur son téléphone mobile, mais toutes les 5 secondes, il va vérifier la météo sur Internet.
Nous devrions attendre l'appel, le sondage appelle toutes les 5 secondes au réseau pour obtenir la météo car l'utilisateur de l'application doit continuer à interagir avec l'écran tactile mobile pour dessiner de jolies images.
Comment utilisez-vous Async et Await
Dans le prolongement de l'exemple ci-dessus, voici un pseudo-code pour l'écrire:
Notes supplémentaires - mise à jour
J'ai oublié de mentionner dans mes notes d'origine qu'en C #, vous ne pouvez attendre que les méthodes qui sont enveloppées dans des tâches. par exemple, vous pouvez attendre cette méthode:
Vous ne pouvez pas attendre des méthodes qui ne sont pas des tâches comme celle-ci:
N'hésitez pas à consulter le code source de la classe Task ici .
la source
Async / Await
En fait, Async / Await sont une paire de mots-clés qui ne sont que du sucre syntaxique pour créer un rappel d'une tâche asynchrone.
Prenons par exemple cette opération:
Le code ci-dessus présente plusieurs inconvénients. Les erreurs ne sont pas transmises et c'est difficile à lire. Mais Async et Await viennent nous aider:
Les appels en attente doivent être dans les méthodes Async. Cela présente certains avantages:
REMARQUE : Async et Await sont utilisés avec les appels asynchrones pour ne pas les effectuer. Vous devez utiliser Task Libary pour cela, comme Task.Run ().
Voici une comparaison entre les solutions en attente et les solutions en attente
Voici la solution non asynchrone:
Voici la méthode asynchrone:
Vous pouvez réellement appeler une méthode asynchrone sans le mot clé wait mais cela signifie que toute exception ici est avalée en mode release:
Async et Await ne sont pas destinés au calcul parallèle. Ils sont utilisés pour ne pas bloquer votre thread principal. Lorsqu'il s'agit d'applications asp.net ou Windows, bloquer votre thread principal en raison d'un appel réseau est une mauvaise chose. Si vous faites cela, votre application ne répondra pas ou même plantera.
Consultez ms docs pour plus d'exemples.
la source
Pour être honnête, je pense toujours que la meilleure explication est celle du futur et des promesses sur Wikipedia: http://en.wikipedia.org/wiki/Futures_and_promises
L'idée de base est que vous disposez d'un pool séparé de threads qui exécutent les tâches de manière asynchrone. Lors de son utilisation. L'objet fait cependant la promesse qu'il exécutera l'opération à un moment donné et vous donnera le résultat lorsque vous le demanderez. Cela signifie qu'il se bloquera lorsque vous demanderez le résultat et ne sera pas terminé, mais s'exécutera dans le pool de threads autrement.
De là, vous pouvez optimiser les choses: certaines opérations peuvent être implémentées en mode asynchrone et vous pouvez optimiser des choses comme les E / S de fichiers et la communication réseau en regroupant les demandes suivantes et / ou en les réorganisant. Je ne suis pas sûr que ce soit déjà dans le cadre de tâches de Microsoft - mais si ce n'est pas le cas, ce serait l'une des premières choses que j'ajouterais.
Vous pouvez réellement implémenter le futur tri de modèle avec des rendements en C # 4.0. Si vous voulez savoir comment cela fonctionne exactement, je peux recommander ce lien qui fait un travail décent: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Cependant, si vous commencez à vous en occuper vous-même, vous remarquerez que vous avez vraiment besoin d'un support linguistique si vous voulez faire toutes les choses intéressantes - c'est exactement ce que Microsoft a fait.
la source
Voir ce violon https://dotnetfiddle.net/VhZdLU (et l'améliorer si possible) pour exécuter une application console simple qui montre les utilisations de Task, Task.WaitAll (), async et attend les opérateurs dans le même programme.
Ce violon devrait effacer votre concept de cycle d'exécution.
Voici l exemple de code
Trace provenant de la fenêtre de sortie:
la source
la source
À un niveau supérieur:
1) Le mot clé Async active l'attente et c'est tout. Le mot clé asynchrone n'exécute pas la méthode dans un thread séparé. La première méthode f async s'exécute de manière synchrone jusqu'à ce qu'elle atteigne l'attente d'une tâche longue.
2) Vous pouvez attendre sur une méthode qui renvoie une tâche ou une tâche de type T. Vous ne pouvez pas attendre sur une méthode async void.
3) Au moment où les rencontres du thread principal attendent sur une tâche longue ou lorsque le travail réel est démarré, le thread principal revient à l'appelant de la méthode actuelle.
4) Si le thread principal voit attendre une tâche en cours d'exécution, il ne l'attend pas et revient à l'appelant de la méthode actuelle. De cette façon, l'application reste réactive.
5) Attendre la tâche de traitement, s'exécutera désormais sur un thread distinct du pool de threads.
6) Lorsque cette tâche d'attente est terminée, tout le code ci-dessous sera exécuté par le thread séparé
Voici l'exemple de code. Exécutez-le et vérifiez l'ID du thread
la source
La façon dont je comprends aussi, il devrait y avoir un troisième mandat ajouté au mélange:
Task
.Async
est juste un qualificatif que vous mettez sur votre méthode pour dire que c'est une méthode asynchrone.Task
est le retour de laasync
fonction. Il s'exécute de manière asynchrone.Vous
await
une tâche. Lorsque l'exécution de code atteint cette ligne, le contrôle revient à l'appelant de votre fonction d'origine environnante.Si, à la place, vous affectez le retour d'une
async
fonction (c'estTask
-à- dire ) à une variable, lorsque l'exécution de code atteint cette ligne, elle continue juste au- delà de cette ligne dans la fonction environnante pendant que l'Task
exécution s'exécute de manière asynchrone.la source
Cet article MDSN: programmation asynchrone avec async et wait (C #) l' explique explicitement:
la source
Dans le code suivant, la méthode HttpClient GetByteArrayAsync renvoie une tâche, getContentsTask. La tâche est une promesse de produire le tableau d'octets réel lorsque la tâche est terminée. L'opérateur d'attente est appliqué à getContentsTask pour suspendre l'exécution dans SumPageSizesAsync jusqu'à ce que getContentsTask soit terminé. En attendant, le contrôle est retourné à l'appelant de SumPageSizesAsync. Lorsque getContentsTask est terminé, l'expression d'attente s'évalue en un tableau d'octets.
la source
Ci-dessous, le code qui lit le fichier Excel en ouvrant la boîte de dialogue, puis utilise async et attend pour exécuter en mode asynchrone le code qui lit une par une la ligne d'Excel et se lie à la grille
la source
Les réponses ici sont utiles comme guide général sur wait / async. Ils contiennent également des détails sur la façon dont wait / async est câblé. Je voudrais partager avec vous une expérience pratique que vous devez savoir avant d'utiliser ce modèle de conception.
Le terme «attendre» est littéral, donc quel que soit le thread sur lequel vous l'appelez attendra le résultat de la méthode avant de continuer. Au premier plan , c'est un désastre . Le thread de premier plan supporte la charge de la construction de votre application, y compris les vues, les modèles de vue, les animations initiales et tout ce que vous avez démarré avec ces éléments. Donc, quand vous attendez le fil de premier plan, vous vous arrêtez l'application. L'utilisateur attend et attend quand rien ne semble se produire. Cela offre une expérience utilisateur négative.
Vous pouvez certainement attendre un fil de fond en utilisant une variété de moyens:
Le code complet de ces remarques se trouve sur https://github.com/marcusts/xamarin-forms-annoyances . Voir la solution appelée AwaitAsyncAntipattern.sln.
Le site GitHub fournit également des liens vers une discussion plus détaillée sur ce sujet.
la source
async / await
c'est du sucre syntaxique pour les rappels, cela n'a rien à voir avec le filetage. msdn.microsoft.com/en-us/magazine/hh456401.aspx Il s'agit d'un code non lié au processeur, par exemple en attente d'entrée ou d'un retard.Task.Run
ne devrait être utilisé que pour le code lié au CPU blog.stephencleary.com/2013/10/…The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing.
Ce n'est pas vrai - peut-être que vous vouliez dire Task.Wait ()? Lorsque vous utilisezawait
, il définit le reste de la méthode comme une continuation à exécuter lorsque tout ce que vous attendez est terminé. Il quitte la méthode dans laquelle vous l'avez utilisé, afin que l'appelant puisse continuer. Ensuite, lorsque la ligne en attente est réellement terminée, elle termine le reste de cette méthode sur un thread (généralement un thread de travail).async/await
consiste à libérer des threads .NET. Lorsque vous effectuezawait
une opération véritablement asynchrone (telle que File.WriteAsync de .NET), elle suspend le reste de la méthode que vous avez utiliséeawait
, afin que l'appelant puisse continuer et potentiellement terminer son objectif. Aucun thread ne bloque ou n'attend l'await
opération -ed. Une fois l'opérationawait
terminée, le reste de laasync/await
méthode est placé sur un thread et exécuté (semblable à une idée de rappel).