La bonne façon de gérer l'exception de la tâche continuewith
Veuillez consulter le code suivant-
static void Main(string[] args)
{
//Get the task.
var task = Task.Factory.StartNew<int>(() => { return div(32, 0); });
//For error handling.
task.ContinueWith(t => { Console.WriteLine(t.Exception.Message); },
TaskContinuationOptions.OnlyOnFaulted);
//If it succeeded.
task.ContinueWith(t => { Console.WriteLine(t.Result); },
TaskContinuationOptions.OnlyOnRanToCompletion);
Console.ReadKey();
Console.WriteLine("Hello");
}
private static int div(int x, int y)
{
if (y == 0)
{
throw new ArgumentException("y");
}
return x / y;
}
Si j'exécute le code en mode release, La sortie est "Une ou plusieurs erreurs se sont produites" et une fois que j'ai frappé à la "touche " Entrée", "Bonjour" est également affiché. Si j'exécute le code en mode debug, la sortie est le même que le mode de libération. Mais lorsque le débogage dans l'IDE, UNE IDE de message d'exception ("une exception non Gérée dans le code de l'utilisateur" ) s'affiche lorsque la commande exécute la ligne de
throw new ArgumentException("y");
Si je continue à partir de là, le programme ne plante pas et affiche le même résultat que mode de diffusion. Est-ce la bonne façon de gérer exception?
- Envisager de passer à async/await: Il est plus facile de syntaxe pour écrire et lire, especcially lors de la manipulation des exceptions.
- vous souhaitez mettre à jour la question à vos exigences: VS2010 et .Net 4.0, comme vous l'avez fait ici.
Vous devez vous connecter pour publier un commentaire.
Vous n'avez probablement pas besoin de séparer le
OnlyOnFaulted
etOnlyOnRanToCompletion
gestionnaires, et vous n'êtes pas de la manipulationOnlyOnCanceled
. Vérifier cette réponse pour plus de détails.Vous voyez l'exception en vertu de l'débogueur parce que vous avez probablement activé dans Debug/options d'Exceptions (Ctrl+Alt+E).
Une exception qui a été levée, mais ce n'est pas manipulé à l'intérieur d'un
Task
action ne sera pas automatiquement re-jeté. Au lieu de cela, il sera enveloppé pour l'avenir de l'observationTask.Exception
(de typeAggregateException
). Vous pouvez accéder à l'exception d'origine commeException.InnerException
:De faire planter le programme dans ce cas, vous avez réellement besoin d'observer l'exception à l'extérieur l'action de la tâche, par exemple en faisant référence à l'
Task.Result
:Plus de détails: Les tâches et les Exceptions Non gérées, La tâche de la gestion des exceptions dans .NET 4.5.
Mis à jour pour répondre au commentaire: ici est de savoir comment je voudrais faire cela dans une INTERFACE utilisateur de l'app avec .NET 4.0 et VS2010:
Pour aussi longtemps que vous ciblez .NET 4.0 et que vous voulez le .NET 4.0, un comportement non des exceptions (c'est à dire, re-jeter lorsque la tâche devient de garbage collector), vous devez explicitement le configurer dans le
app.config
:Vérifier ce pour plus de détails:
Non tâche des exceptions dans .NET4
task = task.ContinueWith()
depuis l'extension de la tâche d'originetask.ContinueWith()
deux fois, mais le résultat n'est pas utilisé. le résultat est une nouvelle tâche qui lorsque attendue (dans l'exemple fait avectask.Result
. dans cet exemple, le Continuer avec les tâches de toujours courir aprèstask.Result
est appelé.ContinueWith
pour ce contexte.task.Result
sera simplement bloquer jusqu'à la fin (quel que soit l'état d'achèvement), et que c'est suffisant pour un exemple simple.task.Result
attendra:return div(32, 0);
MAIS PAS POUR: ` de la Console.WriteLine(t.Exception à la règle.Message); " ouConsole.WriteLine(t.Result);
ce sera probablement courir après ou synchrone aucun moyen de nowing, puisque vous n'avez pas à sauver cette nouvelle tâche. dans ce cas, pas un gros problème, mais peut conduire à de sérieux problème si les gens ne se rendent pas compte. attendre malade effectuer une modification de votre code, de sorte que vous pouvez voir.task = task.ContinueWith()
sera de retour d'uneTask
là plutôt qu'unTask<int>
donc il n'y a tout simplement pas deTask.Result
à observer. s'il vous Plaît s'abstenir de modifier, de publier votre propre réponse si vous le souhaitez.Ce que vous avez là est un
AggregateException
. C'est générée à partir de tâches et vous oblige à vérifier l'intérieur des exceptions à trouver spécifiques. Comme ceci:t.Exception
est déclarée avec le type deAggregateException
, de sorte qu'il suffit de tester pour nullness. Leas
opération n'est pas nécessaire.Comme de .Net 4.5, vous pouvez utiliser
AggregateException.GetBaseException()
de retour "à la racine de la cause de cette exception".https://docs.microsoft.com/en-us/dotnet/api/system.aggregateexception.getbaseexception?view=netframework-4.7.2
La documentation semble être un peu hors de si. Il prétend revenir un autre AggregateException. Cependant, je pense que vous trouverez qu'il retourne à l'exception d'argument qui a été jeté.
La "Une ou plusieurs erreurs se sont produites" vient d'un wrapper exception qui est faite par l'équipe de la piscine. Utilisation
Console.WriteLine(t.Exception.ToString())
pour imprimer l'ensemble de l'exception si vous en avez besoin.IDEs peut capturer automatiquement toutes les exceptions qu'ils ont été manipulés ou pas.
Puisque vous êtes à l'aide de tâches, vous devriez obtenir AggregateException qui enveloppe toutes les exceptions s'est produite lors de l'exécution. Vous voyez
One or more errors occurred
message, car il est par défaut en sortie deAggregateException.ToString()
méthode.Vous avez besoin Poignée méthode de l'exception de l'instance.
Voir aussi la bonne approche pour gérer de telles exceptions ici.