J'aime vraiment cette question:
Le moyen le plus simple de faire un feu et d'oublier la méthode en C #?
Je veux juste savoir que maintenant que nous avons des extensions Parallel en C # 4.0, y a-t-il une meilleure façon plus propre de faire Fire & Forget avec Parallel linq?
c#
.net
.net-4.0
task-parallel-library
fire-and-forget
Jonathon Kresner
la source
la source
Réponses:
Pas une réponse pour 4.0, mais il convient de noter que dans .Net 4.5, vous pouvez rendre cela encore plus simple avec:
Le pragma est de désactiver l'avertissement qui vous indique que vous exécutez cette tâche en tant que feu et oubliez.
Si la méthode à l'intérieur des accolades renvoie une tâche:
Décomposons cela:
Task.Run renvoie une tâche, qui génère un avertissement du compilateur (avertissement CS4014) indiquant que ce code sera exécuté en arrière-plan - c'est exactement ce que vous vouliez, nous désactivons donc l'avertissement 4014.
Par défaut, les tâches tentent de «rétablir le thread d'origine», ce qui signifie que cette tâche s'exécutera en arrière-plan, puis tentera de revenir au thread qui l'a démarré. Souvent, déclenchez et oubliez que les tâches se terminent une fois le thread d'origine terminé. Cela entraînera la levée d'une ThreadAbortException. Dans la plupart des cas, c'est inoffensif - c'est juste vous dire, j'ai essayé de rejoindre, j'ai échoué, mais vous vous en fichez de toute façon. Mais il est toujours un peu bruyant d'avoir ThreadAbortExceptions soit dans vos journaux en production, soit dans votre débogueur en développement local.
.ConfigureAwait(false)
est juste un moyen de rester ordonné et de dire explicitement, exécutez ceci en arrière-plan, et c'est tout.Comme c'est verbeux, en particulier le pragma laid, j'utilise une méthode de bibliothèque pour cela:
Usage:
la source
ConfigureAwait(false)
surTask.Run
quand vous ne faites pasawait
la tâche. Le but de la fonction est dans son nom: "configure wait ". Si vous n'effectuez pasawait
la tâche, vous n'enregistrez pas de continuation et il n'y a pas de code pour que la tâche «rassemble en arrière sur le thread d'origine», comme vous dites. Le plus grand risque est qu'une exception non observée soit renvoyée sur le thread du finaliseur, que cette réponse ne traite même pas.#Disable Warning BC42358
Avec la
Task
classe oui, mais PLINQ est vraiment pour interroger des collections.Quelque chose comme ce qui suit le fera avec Task.
Ou même...
Ou...
Où
FireAway
estDonc, en raison de la concordance des noms de classe et de méthode, cela bat la version de threadpool de six à dix-neuf caractères selon celui que vous choisissez :)
la source
fire and forget in ASP.NET WebForms and windows.close()
:?J'ai quelques problèmes avec la réponse principale à cette question.
Premièrement, dans une véritable situation d' incendie et d'oubli , vous n'aurez probablement pas
await
la tâche, il est donc inutile d'ajouterConfigureAwait(false)
. Si vous n'indiquez pasawait
la valeur renvoyée parConfigureAwait
, cela ne peut avoir aucun effet.Deuxièmement, vous devez être conscient de ce qui se passe lorsque la tâche se termine avec une exception. Considérez la solution simple suggérée par @ ade-miller:
Cela introduit un danger: si une exception non gérée s'échappe
SomeMethod()
, cette exception ne sera jamais, et elle pourrait 1 soit relancée sur le thread finaliseur, plantage de votre application. Je recommanderais donc d'utiliser une méthode d'assistance pour s'assurer que toutes les exceptions qui en résultent sont respectées.Vous pourriez écrire quelque chose comme ceci:
Cette implémentation doit avoir une surcharge minimale: la continuation n'est invoquée que si la tâche ne se termine pas correctement, et elle doit être appelée de manière synchrone (au lieu d'être planifiée séparément de la tâche d'origine). Dans le cas "paresseux", vous n'encourrez même pas une allocation pour le délégué de continuation.
Lancer une opération asynchrone devient alors trivial:
1. C'était le comportement par défaut dans .NET 4.0. Dans .NET 4.5, le comportement par défaut a été modifié de telle sorte que les exceptions non observées ne seraient pas renvoyées sur le thread du finaliseur (bien que vous puissiez toujours les observer via l'événement UnobservedTaskException sur TaskScheduler). Cependant, la configuration par défaut peut être remplacée, et même si votre application nécessite .NET 4.5, vous ne devez pas supposer que les exceptions de tâches non observées seront inoffensives.
la source
ContinueWith
été appelé en raison d'une annulation, la propriété d'exception de l'antécédent sera Null et une exception de référence nulle sera levée. La définition de l'option de continuation de la tâche surOnlyOnFaulted
supprimera la nécessité de vérifier la valeur nulle ou de vérifier si l'exception est nulle avant de l'utiliser.Task
devient un détail d'implémentation.Task
" n'est pas la même chose que "Je veux un moyen simple de lancer une opération en arrière-plan, ne jamais observer son résultat, et je me fiche du mécanisme utilisé pour le faire." Sur cette base, je soutiens ma réponse à la question qui a été posée .fire and forget
dans ASP.NET WebForms etwindows.close()
?Juste pour résoudre un problème qui se produira avec la réponse de Mike Strobel:
Si vous utilisez
var task = Task.Run(action)
et après attribuez une continuation à cette tâche, vous courrez le risque deTask
lever une exception avant d'affecter une continuation de gestionnaire d'exceptions auTask
. Ainsi, la classe ci-dessous devrait être exempte de ce risque:Ici, le
task
n'est pas exécuté directement, au lieu de cela, il est créé, une continuation est affectée, et alors seulement la tâche est exécutée pour éliminer le risque que la tâche termine l'exécution (ou lève une exception) avant d'attribuer une continuation.La
Run
méthode ici renvoie la suiteTask
pour que je puisse écrire des tests unitaires en m'assurant que l'exécution est terminée. Vous pouvez cependant l'ignorer en toute sécurité dans votre utilisation.la source