J'ai quelques problèmes avec la réponse principale à cette question.
D'abord, dans un véritable feu et oublie situation, vous ne pourrez probablement pas await
la tâche, il est donc inutile d'ajouter ConfigureAwait(false)
. Si vous ne await
la valeur renvoyée par ConfigureAwait
alors il ne peut pas avoir d'effet.
Deuxièmement, vous devez être conscient de ce qui se passe lorsque la tâche se termine par une exception. Considérez la solution simple que @ade-miller a suggérée :
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
Cela introduit un risque : si une exception non gérée s'échappe de l'application SomeMethod()
cette exception ne sera jamais respectée, et pourra 1 sera relancé sur le thread du finalisateur, ce qui fera planter votre application. Je recommande donc d'utiliser une méthode d'aide pour s'assurer que toutes les exceptions qui en résultent sont respectées.
Vous pourriez écrire quelque chose comme ça :
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 mise en œuvre devrait avoir une surcharge minimale : la continuation n'est invoquée que si la tâche ne se termine pas avec succès, et elle devrait être invoquée de manière synchrone (par opposition à une planification séparée de la tâche originale). Dans le cas "paresseux", vous n'aurez même pas besoin d'allocation pour le délégué de continuation.
Le lancement d'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 manière à ce que les exceptions non observées soient <em>no </em>sont rejetées sur le thread du finalisateur (bien que vous puissiez toujours les observer via l'événement UnobservedTaskException sur TaskScheduler). Cependant, la configuration par défaut peut être modifié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.
1 votes
La réponse à cette question s'applique toujours à .NET 4.0. Il n'y a pas plus simple que QueueUserWorkItem.
0 votes
Cela répond-il à votre question ? La façon la plus simple de faire une méthode "fire and forget" en C# ?