2009-07-30 3 views
13

J'ai une application winforms. Winforms commence par Program.cs où nous avons défini main(). J'ai placé ce code dans le bloc try-catch.Pourquoi l'exception win32 n'est pas interceptée par le mécanisme de gestion des exceptions C#

[STAThread] 
    static void Main() 
    { 
     try 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new frmSplash()); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
      if (ex.InnerException != null) 
      { 
       MessageBox.Show(ex.InnerException.ToString()); 
      } 
     } 
    } 

Chaque fois qu'il ya une exception win32, ce mécanisme échoue et unhandled message d'exception est levée et application se bloque.
J'ai 2 questions concernant ce code:

1) Pourquoi les exceptions win32 ne sont pas interceptées.

2) Est-ce une bonne pratique d'attraper des exceptions au plus haut niveau.

+0

Wow, je n'ai jamais vraiment pensé à cela, bonne question et bonnes réponses :) – leppie

+0

S'il vous plaît commenter sur la deuxième question aussi. – Rohit

+0

Peut-être que vous pourriez en faire une deuxième question SO ;-) – Mac

Répondre

12

EDIT: comme Pratik souligné, la réponse suivante s'applique uniquement à .NET 1.0 et .NET 1.1. À partir de .NET 2.0, l'exception non-CLS doit être considérée comme RuntimeWrappedException. Parce que les exceptions Win32 ne dérivent pas de la classe .NET Exception. Essayez:

try { 
} catch (Exception ex) { 
    // .NET exception 
} catch { 
    // native exception 
} 

Voir Catch non-CLSCompliant exceptions in general handlers pour plus d'informations.

+4

Ceci n'est pas requis dans .Net 2.0 par défaut. Toutes les exceptions non CLS sont rappées en RuntimeWrappedException. Voir http://msdn.microsoft.com/en-us/library/ms404228.aspx – softveda

+0

Win32Exception

+0

@Pratik: merci pour le lien. @Tommy Carlier: cf. Le lien de Pratik ... – Mac

0

Vous devrez peut-être attraper Win32Exception (ou ExternalException) au lieu

http://msdn.microsoft.com/en-us/library/system.componentmodel.win32exception.aspx

Je crois me souvenir que Win32Exception hérite de ExternalException mais ExternalException ne hérite d'exception pour ne pas être pris par votre code .

Editer: Voir les autres réponses pour pourquoi c'est faux!

Edit 2: En ce qui concerne la deuxième partie, comme indiqué par AnthonyWJones Il est de bonnes manières pour informer l'utilisateur qu'un problème a causé la fermeture de l'application mais je vous conseille d'utiliser une déclaration en anglais simple à l'utilisateur et en consignant la pile d'exceptions dans un fichier journal pour votre propre usage.

+1

Ces deux sont dérivées de l'exception, donc à la surface de celui-ci la capture dans la question devrait fonctionner. Pour pourquoi il ne voit pas ma réponse. – AnthonyWJones

3

L'exécution de Application.Run ne génère pas d'erreur. Cela se passe sur un autre thread (ou au moins de manière asynchrone).

Sa bonne idée d'informer l'utilisateur de manière amicale que l'application a échoué avant qu'il ne disparaisse complètement, mais ce n'est pas une bonne idée de simplement attraper puis continuer.

3

Bien que je ne sache pas pourquoi votre bloc catch ne fonctionne pas, essayez d'utiliser le Application ThreadException Event. Cela devrait intercepter toute erreur dans les threads d'application. Ajoutez un gestionnaire d'événements avant d'appeler Application.Run.

Pour votre deuxième réponse définitivement oui. Je développe et maintient une application winforms d'entreprise qui parle avec un backend de service web sur les threads de fond. Si des blocages d'appels WebService gèrent l'événement threadexception de l'application (et aussi l'exception apphandding unhandledexception), consignez et affichez une erreur que les utilisateurs professionnels peuvent signaler et leur permettre de continuer sans écraser l'application.

0

1) Les exceptions Win32 doivent être interceptées. Peut-être que l'exception est lancée à partir d'un thread d'arrière-plan ou du thread GC?

2) Cela dépend de la structure de votre application. Par exemple, si votre interface de notification d'erreur était liée au formulaire principal (par exemple, vous devez invoquer le thread d'interface utilisateur d'un thread de travail), il serait stupide d'afficher une interface utilisateur dans un bloc de code en dehors du code boucle. Cependant, si votre exemple de code est monothread, tout ira bien.

1

Essayez vous abonner à ces événements avant le démarrage de votre application (Application.Run):

Vous pouvez alors vous débarrasser de votre bloc try catch. Je pense que c'est une mauvaise habitude d'attraper des exceptions au plus haut niveau, mais vous ne pouvez pas l'éviter! Au cours du développement (débogage), ces exceptions ne devraient pas être interceptées et l'application devrait faire la chose la plus méchante possible (crash?). En production (Release), vous souhaiterez que votre application se dégrade le mieux possible même lorsque des exceptions non gérées se produisent. C'est l'une des rares utilisations que j'ai trouvées pour le DEBUG preprocessor variable.

+0

Voilà: 2 réponses en une. Lequel allez-vous pour (ou contre)? – Mac

Questions connexes