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'ajouter ConfigureAwait(false)
. Si vous n'indiquez pas await
la valeur renvoyée par ConfigureAwait
, 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:
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
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:
public static class Blindly
{
private static readonly Action<Task> DefaultErrorContinuation =
t =>
{
try { t.Wait(); }
catch {}
};
public static void Run(Action action, Action<Exception> handler = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var task = Task.Run(action); // Adapt as necessary for .NET 4.0.
if (handler == null)
{
task.ContinueWith(
DefaultErrorContinuation,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(
t => handler(t.Exception.GetBaseException()),
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
}
}
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:
Blindly.Run(SomeMethod); // Ignore error
Blindly.Run(SomeMethod, e => Log.Warn("Whoops", e)); // Log error
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.