Comment puis-je attendre qu'une void async
méthode termine son travail?
par exemple, j'ai une fonction comme ci-dessous:
async void LoadBlahBlah()
{
await blah();
...
}
maintenant je veux m'assurer que tout a été chargé avant de continuer ailleurs.
c#
asynchronous
MBZ
la source
la source
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
est trompeur. Cela n'attend pas la fin de la fonction asynchroneblah
, il attend juste la création (triviale) de la tâche et se poursuit immédiatement avant lablah()
fin.Thread.Sleep
n'est pas asynchrone. Cette question concerne l'attente d'uneasync void
fonction, disonsasync void blah() { Task.Delay(10000); }
Si vous pouvez changer la signature de votre fonction en
async Task
alors vous pouvez utiliser le code présenté icila source
La meilleure solution est d'utiliser
async Task
. Vous devez éviterasync void
pour plusieurs raisons, dont la composabilité.Si la méthode ne peut pas être renvoyée
Task
(par exemple, c'est un gestionnaire d'événements), vous pouvez utiliserSemaphoreSlim
pour que la méthode signale qu'elle est sur le point de se terminer. Pensez à faire cela dans unfinally
bloc.la source
faites un AutoResetEvent, appelez la fonction puis attendez AutoResetEvent, puis définissez-le dans async void lorsque vous savez que c'est fait.
Vous pouvez également attendre une tâche qui revient de votre asynchrone void
la source
Vous n'avez pas vraiment besoin de faire quoi que ce soit manuellement, le
await
mot - clé interrompt l'exécution de la fonction jusqu'aublah()
retour.T
est le type d'objetblah()
renvoyéVous ne pouvez pas vraiment
await
unevoid
fonction doncLoadBlahBlah()
ne peut pas êtrevoid
la source
LoadBlahBlah()
finir, pasblah()
Je sais que c'est une vieille question, mais c'est toujours un problème dans lequel je continue à marcher, et pourtant il n'y a toujours pas de solution claire pour le faire correctement lorsque vous utilisez async / await dans une méthode de signature async void.
Cependant, j'ai remarqué que .Wait () fonctionne correctement dans la méthode void.
et comme async void et void ont la même signature, vous devrez peut-être faire ce qui suit.
Async / await assez confus ne bloque pas sur le code suivant.
Lorsque vous décompilez votre code, je suppose que async void crée une tâche interne (tout comme une tâche async), mais puisque la signature ne prend pas en charge le retour de ces tâches internes
cela signifie qu'en interne la méthode async void pourra toujours "attendre" les méthodes asynchrones en interne. mais extérieurement incapable de savoir quand la tâche interne est terminée.
Ma conclusion est donc qu'async void fonctionne comme prévu, et si vous avez besoin de commentaires de la tâche interne, vous devez utiliser la signature de tâche async à la place.
j'espère que ma randonnée a du sens pour quiconque cherche également des réponses.
Edit: J'ai créé un exemple de code et je l'ai décompilé pour voir ce qui se passe réellement.
Se transforme en (modifier: je sais que le code du corps n'est pas ici mais dans les statemachines, mais les statemachines étaient fondamentalement identiques, donc je n'ai pas pris la peine de les ajouter)
Ni AsyncVoidMethodBuilder ni AsyncTaskMethodBuilder n'ont en fait de code dans la méthode Start qui leur indiquerait de les bloquer, et s'exécuteraient toujours de manière asynchrone après leur démarrage.
ce qui signifie sans la tâche de retour, il n'y aurait aucun moyen de vérifier si elle est terminée.
comme prévu, il démarre uniquement la tâche en cours d'exécution asynchrone, puis continue dans le code. et la tâche asynchrone, commence d'abord la tâche, puis la renvoie.
donc je suppose que ma réponse serait de ne jamais utiliser async void, si vous avez besoin de savoir quand la tâche est terminée, c'est à cela que sert async Task.
la source