Quelle est la différence entre Application.ThreadException et AppDomain.CurrentDomain.UnhandledException?

107

D'accord, c'est facile:

  • Quelle est la différence entre Application.ThreadExceptionet
    AppDomain.CurrentDomain.UnhandledException?

  • Dois-je gérer les deux?

Merci!

JohnIdol
la source

Réponses:

98

Application.ThreadException est spécifique à Windows Forms. Winforms exécute des gestionnaires d'événements en réponse aux messages qui lui sont envoyés par Windows. L'événement Click par exemple, je suis sûr que vous les connaissez. Si un tel gestionnaire d'événements lève une exception, il y a un arrêt arrière dans la boucle de message Winforms qui intercepte cette exception.

Ce backstop déclenche l' événement Application.ThreadException . Si vous ne le remplacez pas, l'utilisateur obtiendra un ThreadExceptionDialog . Ce qui lui permet d'ignorer l'exception et de continuer à exécuter votre programme. Pas une bonne idée d'ailleurs.

Vous pouvez désactiver ce comportement en appelant Application.SetUnhandledExceptionMode () dans la méthode Main () dans Program.cs. Sans ce backstop en place, la chose habituelle se produit lorsqu'un thread meurt d'une exception non gérée : AppDomain.UnhandledException se déclenche et le programme se termine.

Fwiw: "ThreadException" était un très mauvais choix de nom. Cela n'a rien à voir avec les threads.

Hans Passant
la source
Et comment empêcher l'application WinForms de planter lors de l'apparition de Application.ThreadException. J'ai soulevé une question à ce sujet [ici ] avec mon petit code C #.
Mahesha999
2
Je le lis toujours comme une exception de thread d'application, étant donné que winforms est lié à un seul thread.
Gusdor
36

De la source :

Dans les applications qui utilisent Windows Forms, les exceptions non gérées dans le thread d'application principal provoquent le déclenchement de l' Application.ThreadException événement. Si cet événement est géré, le comportement par défaut est que l'exception non gérée ne met pas fin à l'application, bien que l'application reste dans un état inconnu. Dans ce cas, l' UnhandledException événement n'est pas déclenché. Ce comportement peut être modifié en utilisant le fichier de configuration de l'application ou en utilisant la Application.SetUnhandledExceptionModeméthode pour modifier le mode UnhandledExceptionMode.ThrowExceptionavant que le ThreadException gestionnaire d'événements ne soit connecté. Cela s'applique uniquement au thread d'application principal. L' UnhandledException événement est déclenché pour les exceptions non gérées levées dans d'autres threads.

À partir de Visual Studio 2005 , l' infrastructure d' application Visual Basic fournit un autre événement pour les exceptions non gérées dans le thread d'application principal - WindowsFormsApplicationBase.UnhandledException. Cet événement a un objet d'arguments d'événement avec le même nom que l'objet d'arguments d'événement utilisé par AppDomain.UnhandledException, mais avec des propriétés différentes. En particulier, cet objet d'arguments d'événement a une ExitApplicationpropriété qui permet à l'application de continuer à s'exécuter, en ignorant l'exception non gérée (et en laissant l'application dans un état inconnu). Dans ce cas, l'événement AppDomain.UnhandledException n'est pas déclenché.

Application.ThreadExceptionpeut être intercepté et l' application pourrait continuer (en général, ce n'est pas une bonne idée, mais pour l'application comme l'exécution périodique de certaines actions, c'est une bonne solution).

Pour intercepter les exceptions qui se produisent dans les threads non créés et détenus par Windows Forms, utilisez le AppDomain.UnhandledException. Il permet à l'application de consigner des informations sur l'exception avant que le gestionnaire par défaut du système ne signale l'exception à l'utilisateur et mette fin à l'application.
Le traitement de cette exception n'empêche pas la fin de l'application.
Le maximum qui pourrait être fait (les données du programme peuvent être corrompues lorsque les exceptions ne sont pas gérées) est la sauvegarde des données du programme pour une récupération ultérieure. Après cela, le domaine d'application est déchargé et l'application se termine.

À partir de .NET 4 , cet événement n'est pas déclenché pour les exceptions qui altèrent l'état du processus, telles que les débordements de pile ou les violations d'accès, sauf si le gestionnaire d'événements est critique pour la sécurité et possède l' HandleProcessCorruptedStateExceptionsAttribute attribut.

Pour plus de détails, consultez MSDN .

serhio
la source
18

OK - je l'avais devant moi, ce morceau de code de msdn est assez explicite:

public static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new 
        ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

    // Set the unhandled exception mode to force all Windows Forms 
    // errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
    Application.Run(new ErrorHandlerForm());
}
JohnIdol
la source
3
c'est en contraste avec l'autre réponse de serhio quand il dit: UnhandledExceptionMode.ThrowException doit être défini avant que le gestionnaire d'événements ThreadException ne soit connecté. Je ne sais pas si l'ordre compte vraiment ...
Davide Piras
@DavidePiras oui, et il y a quelque chose de plus trouble. SetUnhandledException ne semble pas faire de différence dans mon cas.
nawfal
0

Eh bien, le fait est que, ThreadExceptionse produit en raison d'un problème avec votre thread, le Unhandled Exceptionest déclenché si le code lève une exception qui n'est pas gérée.

Le moyen le plus simple de provoquer le second est de créer une application sans essayer ... attraper des blocs et lancer une exception.

Maintenant, si vous avez besoin d'une assurance, vous pouvez les gérer tous les deux, mais si vous capturez et gérez votre exceptionscorrectement, vous ne devriez pas avoir besoin du UnhandledExceptiongestionnaire car c'est un peu comme un fourre-tout.

Joshua Cauble
la source
merci - ce que je n'étais pas trop clair, c'était si gérer UnhandledException j'attraperais également ThreadException - ce qui ne semble pas être le cas
JohnIdol