Nous avons une application WPF dont certaines parties peuvent lever des exceptions lors de l'exécution. J'aimerais intercepter globalement toute exception non gérée et les enregistrer, mais sinon, continuez l'exécution du programme comme si rien ne s'était passé (un peu comme les VB On Error Resume Next
).
Est-ce possible en C #? Et si oui, où aurais-je exactement besoin de mettre le code de gestion des exceptions?
Actuellement, je ne vois aucun point unique où je pourrais boucler un try
/ catch
autour et qui intercepterait toutes les exceptions qui pourraient se produire. Et même alors, j'aurais laissé tout ce qui a été exécuté à cause de la capture. Ou est-ce que je pense ici dans des directions horriblement erronées?
ETA: Parce que de nombreuses personnes ci-dessous l'ont souligné: L'application n'est pas destinée au contrôle des centrales nucléaires. S'il se bloque, ce n'est pas très grave, mais des exceptions aléatoires qui sont principalement liées à l'interface utilisateur sont une nuisance dans le contexte où il serait utilisé. Il y en avait (et il y en a probablement encore) et comme il utilise une architecture de plug-in et peut être étendu par d'autres (également des étudiants dans ce cas; donc pas de développeurs expérimentés capables d'écrire du code sans erreur).
Quant aux exceptions qui sont interceptées: je les enregistre dans un fichier journal, y compris la trace de pile complète. C'était tout l'intérêt de cet exercice. Juste pour contrer ces gens qui prenaient mon analogie avec OERN de VB trop littéralement.
Je sais qu'ignorer aveuglément certaines classes d'erreurs est dangereux et peut corrompre mon instance d'application. Comme dit précédemment, ce programme n'est essentiel à la mission de personne. Personne sain d'esprit ne parierait la survie de la civilisation humaine dessus. C'est simplement un petit outil pour tester certaines approches de conception par rapport à. génie logiciel.
Pour l'utilisation immédiate de l'application, il n'y a pas beaucoup de choses qui peuvent se produire sur une exception:
- Aucune gestion des exceptions - boîte de dialogue d'erreur et sortie de l'application. L'expérience doit être répétée, mais probablement avec un autre sujet. Aucune erreur n'a été enregistrée, ce qui est regrettable.
- Gestion des exceptions générique - erreur bénigne piégée, aucun dommage causé. Cela devrait être le cas commun à en juger par toutes les erreurs que nous avons vues pendant le développement. Ignorer ce type d'erreurs ne devrait pas avoir de conséquences immédiates; les structures de données de base sont suffisamment testées pour pouvoir y survivre facilement.
- Gestion des exceptions générique - erreur grave interceptée, peut-être planter ultérieurement. Cela peut arriver rarement. Nous ne l'avons jamais vu jusqu'à présent. L'erreur est enregistrée de toute façon et un plantage peut être inévitable. C'est donc conceptuellement similaire au tout premier cas. Sauf que nous avons une trace de pile. Et dans la majorité des cas, l'utilisateur ne le remarquera même pas.
En ce qui concerne les données d'expérience générées par le programme: Une erreur grave entraînerait au pire le fait qu'aucune donnée ne soit enregistrée. Des changements subtils qui modifient légèrement le résultat de l'expérience sont très peu probables. Et même dans ce cas, si les résultats semblent douteux, l'erreur a été enregistrée; on peut encore jeter ce point de données s'il s'agit d'une valeur aberrante totale.
Pour résumer: Oui, je me considère toujours au moins partiellement sain d'esprit et je ne considère pas une routine globale de gestion des exceptions qui laisse le programme en cours d'exécution être nécessairement totalement mauvais. Comme indiqué deux fois auparavant, une telle décision peut être valable, selon l'application. Dans ce cas, il a été jugé une décision valide et non une connerie totale et totale. Pour toute autre application, cette décision peut sembler différente. Mais s'il vous plaît, n'accusez pas moi ou les autres personnes qui ont travaillé sur ce projet pour potentiellement faire exploser le monde simplement parce que nous ignorons les erreurs.
Note latérale: Il y a exactement un utilisateur pour cette application. Ce n'est pas quelque chose comme Windows ou Office qui est utilisé par des millions de personnes où le coût de la bulle d'exceptions pour l'utilisateur serait déjà très différent en premier lieu.
On Error Resume Next
n'est pas possible en C #. Après unException
(C # n'a pas "d'erreurs"), vous ne pouvez pas simplement reprendre avec l'instruction suivante: l'exécution se poursuivra dans uncatch
bloc - ou dans l'un des gestionnaires d'événements décrits dans les réponses ci-dessous.Réponses:
Utilisez le
Application.DispatcherUnhandledException Event
. Voir cette question pour un résumé (voir la réponse de Drew Noakes ).Sachez qu'il y aura toujours des exceptions qui empêcheront une reprise réussie de votre application, comme après un débordement de pile, une mémoire épuisée ou une perte de connectivité réseau pendant que vous essayez d'enregistrer dans la base de données.
la source
Exemple de code utilisant NLog qui interceptera les exceptions levées de tous les threads de l'AppDomain , du thread du répartiteur d'interface utilisateur et des fonctions asynchrones :
App.xaml.cs:
la source
UnhandledException
gestionnaire. J'ai dû regarder la visionneuse du journal des événements de Windows pour trouver ce qui se passait ...e.Handled = true;
àUnhandledException
que l'application ne se bloquera pas sur les exceptions d'interface utilisateurAppDomain.UnhandledException, événement
la source
En plus de ce que d'autres ont mentionné ici, notez que la combinaison
Application.DispatcherUnhandledException
(et ses similitudes ) avecdans le
app.config
vous empêchera votre exception de threads secondaires de fermer l'application.la source
Voici un exemple complet utilisant
NLog
la source
Comme "VB's On Error Resume Next?" Cela semble un peu effrayant. La première recommandation est de ne pas le faire. La deuxième recommandation est de ne pas le faire et de ne pas y penser. Vous devez mieux isoler vos défauts. Quant à la façon d'aborder ce problème, cela dépend de la façon dont votre code est structuré. Si vous utilisez un modèle comme MVC ou similaire, cela ne devrait pas être trop difficile et ne nécessiterait certainement pas un avaleur d'exceptions global. Deuxièmement, recherchez une bonne bibliothèque de journalisation comme log4net ou utilisez le traçage. Nous aurions besoin de plus de détails, tels que les types d'exceptions dont vous parlez et les parties de votre application susceptibles d'entraîner la levée d'exceptions.
la source