2016-02-29 1 views
2

J'ai un programme C# qui exécute une application de la barre d'état système - transférer/déplacer/créer/éditer des fichiers en arrière-plan.Est-il possible d'avoir un gestionnaire d'exceptions pour plusieurs temporisateurs dans une classe C#?

Il y a beaucoup de gestion des exceptions et de gestion de boucle pour éviter que le programme ne plante ou ne se bloque si le manuel d'utilisateur supprime un fichier avec lequel le programme travaille.

Malheureusement, l'un des ordinateurs sur lequel s'exécute le programme est celui où le programme plante. L'ordinateur est très difficile à obtenir et ne peut pas avoir de logiciel de débogage chargé (c'est un PC embarqué à l'extérieur sans accès au réseau).

J'ai essayé de trouver la cause du crash (comme une exception non gérée) mais je n'ai rien trouvé et je n'ai pas accès au PC car il est dans un endroit éloigné.

J'espérais trouver un moyen d'utiliser AppDomain/un UnhandledExceptionEventHandler pour attraper toutes les exceptions non gérées et les enregistrer pour le diagnostic. Toutefois, l'exception que j'ai créée (délibérément) dans le bureau à l'intérieur de la classe "DoSomething.class" plante l'application WinForm au lieu de consigner l'erreur d'exception.

Mon code est:

//Current domain for the unhandled exception handling 
    AppDomain currentDomain; 

    [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)] 
    public MainForm() 
    { 
     InitializeComponent(); 

     currentDomain = AppDomain.CurrentDomain; 
     currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler); 


     CreateTimer.Interval = Settings.Default.CreateTimer; 
     CreateTimer.Start(); 
     RunCopyProtocol(); 

     ChangeFilesTimer.Interval = 10000; 
     ChangeFilesTimer.Start(); 
     RunChangeFiles(); 

     throw new Exception("ABC"); 

    } 

    public void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) 
    { 
     try 
     { 
      Exception ex = (Exception)args.ExceptionObject; 
      SetLabel(ex); 
     } 
     finally { } 
    } 

    private string SetLabel(Exception ex) 
    { 
     String str; 

     str = ex.Message; 
     Label1.Text = str; 

     return str; 
    } 

    private void ChangeFilesTimer_Tick(object sender, EventArgs e) 
    { 
     RunChangeFiles(); 
     throw new Exception("2"); 
    } 

Pourquoi ne pas lancer une nouvelle exception appelle l'erreur d'exception non gérée? Comment utiliser AppDomain pour obtenir le gestionnaire d'exceptions non gérées pour gérer cette exception/exceptions dans RunChangeFiles?

Code de AppDomain est basé de MSDN examples

+1

Vous pouvez avoir une idée erronée de ce que AppDomain.UnhandledException va vous permettre de faire. Cela n'empêche pas l'application de se terminer lorsqu'une exception non gérée se produit. C'est simplement une notification qui vous permet de nettoyer ou de vous connecter avant la fin du processus. –

Répondre

2

Si votre minuterie est System.Timers.Timer la raison est documentée par MSDN here:

Les prises de composants de la minuterie et supprime toutes les exceptions lancées par des gestionnaires d'événements pour la Evénement écoulé.

Jetez un oeil à cette même question: How do I get the Exception that happens in Timer Elapsed event?

Vous devez attraper les exceptions qui sont jetés dans le gestionnaire écoulé, et les réémettre sur un fil ThreadPool.

En utilisant votre code ci-dessus et l'extension de la réponse de la question référencée:

private void ChangeFilesTimer_Tick(object sender, EventArgs e) 
{ 
    try 
    { 
     RunChangeFiles(); 
    } 
    catch (Exception ex) 
    { 
     ThreadPool.QueueUserWorkItem(
      _ => { throw new Exception("Exception on timer thread.", ex); }); 
    } 
} 

Si votre minuterie est un System.Windows.Forms.Timer alors vous devrez connecter à l'événement Application.ThreadException pour gérer les exceptions non gérées. Abonnez-vous à cet événement avant d'appeler Application.Run().


Vous pouvez également gérer l'enregistrement de l'Exception dans un bloc local de gestion des exceptions avant rethrowing l'exception.

try 
{ 
    /// ... 
} 
catch (Exception ex) 
{ 
    if (ex is ArgumentException) 
    { 
     /// handle known or specific exceptions here 
    } 
    else 
    { 
     /// log then rethrow unhandled exceptions here 
     logExceptions(ex); 
     throw; 
    } 
} 
+0

Si je mets un "throw new Exception (" TEST ");" Dans le MainForm(). Il jette toujours l'exception sans être attrapé par le gestionnaire. La minuterie supprime-t-elle simplement d'autres événements en s'exécutant? (c'est-à-dire non seulement quand il s'est écoulé?) – Luke

+0

public MainForm() { InitializeComponent(); currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException + = new UnhandledExceptionEventHandler (UnhandledExceptionHandler); CreateTimer.Interval = Paramètres.Default.CreateTimer; CreateTimer.Start(); RunCopyProtocol(); ChangeFilesTimer.Interval = 10000; ChangeFilesTimer.Start(); RunChangeFiles(); throw new Exception ("123") } Ce fut le code. Avec la nouvelle exception levée à la fin de MainForm() après l'abonnement du gestionnaire – Luke

+0

Vous lancez l'exception de test sur un thread d'interface utilisateur. Pour gérer cela, vous devez vous connecter à l'événement 'Application.ThreadException'. Regardez ici: http://stackoverflow.com/a/5762806/4267590 et sur MSDN [ici] (https://msdn.microsoft.com/fr-fr/library/system.windows.forms.application.threadexception%28v = vs.110% 29.aspx) – khargoosh