Dans quels scénarios voudrait-on utiliser
public async Task AsyncMethod(int num)
au lieu de
public async void AsyncMethod(int num)
Le seul scénario auquel je peux penser est si vous avez besoin de la tâche pour pouvoir suivre sa progression.
De plus, dans la méthode suivante, les mots clés asynchrones et en attente sont-ils inutiles?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
c#
asynchronous
.net-4.5
user981225
la source
la source
Foo()
deviendraitFooAsync()
.Thread.Sleep
avec vos tâches, vous devriezawait Task.Delay(num)
plutôtTask.Delay
n'est pas le cas,Task.AsyncDelay
car toutes les méthodes de la tâche sont Asyncasync void
placeasync Task
. La méthode s'est bloquée car elle utilisait un objet de contexte Entity Framework déclaré en tant que membre du contrôleur a été supprimé avant la fin de l'exécution de la méthode. L'infrastructure a disposé le contrôleur avant que sa méthode ne soit exécutée. J'ai changé la méthode en tâche asynchrone et cela a fonctionné.Réponses:
1) Normalement, vous voudriez retourner a
Task
. La principale exception devrait être lorsque vous devez avoir unvoid
type de retour (pour les événements). S'il n'y a aucune raison de ne pas autoriser l'appelant à effectuerawait
votre tâche, pourquoi la refuser?2) les
async
méthodes qui retournentvoid
sont spéciales sous un autre aspect: elles représentent des opérations asynchrones de niveau supérieur et ont des règles supplémentaires qui entrent en jeu lorsque votre tâche renvoie une exception. La façon la plus simple est de montrer la différence avec un exemple:f
L'exception est toujours "observée". Une exception qui laisse une méthode asynchrone de niveau supérieur est simplement traitée comme toute autre exception non gérée.g
L'exception n'est jamais observée. Lorsque le garbage collector vient nettoyer la tâche, il voit que la tâche a généré une exception et que personne n'a géré l'exception. Lorsque cela se produit, leTaskScheduler.UnobservedTaskException
gestionnaire s'exécute. Vous ne devriez jamais laisser cela se produire. Pour utiliser votre exemple,Oui, utilisez
async
etawait
ici, ils s'assurent que votre méthode fonctionne toujours correctement si une exception est levée.pour plus d'informations, voir: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
la source
f
au lieu deg
dans mon commentaire. L'exception def
est passée àSynchronizationContext
.g
va augmenterUnobservedTaskException
, maisUTE
ne plante plus le processus s'il n'est pas géré. Il existe des situations où il est acceptable d'avoir des "exceptions asynchrones" comme celle-ci qui sont ignorées.WhenAny
plusieursTask
entraînant des exceptions. Vous n'avez souvent qu'à gérer le premier, et vous voulez souvent ignorer les autres.WhenAny
en premier lieu s'il est correct d'ignorer les autres exceptions: le principal cas d'utilisation que j'ai pour lui finit toujours par attendre les tâches restantes à la fin de toute tâche , avec ou sans exception.J'ai rencontré cet article très utile sur
async
etvoid
écrit par Jérôme Laban: https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void .htmlL'essentiel est qu'un an
async+void
peut planter le système et ne doit généralement être utilisé que sur les gestionnaires d'événements secondaires de l'interface utilisateur.la source
J'ai eu une idée claire de ces déclarations.
Les exceptions d'une méthode Async Void ne peuvent pas être détectées avec Catch
Ces exceptions peuvent être observées à l'aide d'AppDomain.UnhandledException ou d'un événement fourre-tout similaire pour les applications GUI / ASP.NET, mais l'utilisation de ces événements pour la gestion régulière des exceptions est une recette pour la non-maintenance (elle bloque l'application).
Les méthodes async void ont une sémantique de composition différente. Les méthodes asynchrones renvoyant Task ou Task peuvent être facilement composées à l'aide de wait, Task.WhenAny, Task.WhenAll et ainsi de suite. Les méthodes asynchrones renvoyant void ne permettent pas de notifier facilement le code appelant qu'elles ont terminé. Il est facile de démarrer plusieurs méthodes void asynchrones, mais il n'est pas facile de déterminer quand elles ont fini. Les méthodes async void notifieront leur SynchronizationContext au démarrage et à la fin, mais un SynchronizationContext personnalisé est une solution complexe pour le code d'application normal.
La méthode Async Void est utile lors de l'utilisation d'un gestionnaire d'événements synchrone car elle déclenche ses exceptions directement sur le SynchronizationContext, ce qui est similaire à la façon dont les gestionnaires d'événements synchrones se comportent
Pour plus de détails, consultez ce lien https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
la source
Le problème avec l'appel async void est que vous ne récupérez même pas la tâche, vous n'avez aucun moyen de savoir quand la tâche de la fonction est terminée (voir https://blogs.msdn.microsoft.com/oldnewthing/20170720-00/ ? p = 96655 )
Voici les trois façons d'appeler une fonction asynchrone:
la source
Je pense que vous pouvez également l'utiliser
async void
pour lancer des opérations en arrière-plan, tant que vous prenez soin de détecter les exceptions. Pensées?la source
Ma réponse est simple, vous ne pouvez pas attendre la méthode nulle
Donc, si la méthode est asynchrone, il vaut mieux être attendu, car vous pouvez perdre l'avantage asynchrone.
la source
Selon la documentation de Microsoft , ne doit JAMAIS utiliser
async void
la source