none
Exception aus Thread fangen RRS feed

  • Frage

  • Hallo,

    ich will eine Exception, die in einem Thread geworfen wird, in der Application fangen. Weiß jemand wie ob und wie das funktioniert?

    static class Program
      {
        static void Main()
        {
          ThreadStart threadStart = new ThreadStart(doWork);
          Thread worker = new Thread(threadStart);
          worker.Start();
        }
    
        private static void doWork()
        {
          try
          {
            //do something
          }
          catch (Exception ex)
          {
            throw ex;
          }
        }
      }

    Merci,

    Andre

    Donnerstag, 2. September 2010 13:36

Antworten

  • Hallo HP.,

    da das je nach Applikations-Typ unterschiedlich implementiert wird, müsste ich Dir die Frage nach dem App-Typ stellen (ASP.NET/WinFormWPF/Silverlight) 

    Trotzdem gebe ich Dir schon mal den Rat, dass es oft sinnvoll ist, das über ein globales Abfangen der Exception zu machen.
    Das haben wir immer recht vorteilhaft einsetzen können. Hier Beispiele/Hinweise: [global exception Handling C# - Google-Suche].
    Unter WinForms habe ich meist das Verfahren:

       [Application.ThreadException-Ereignis (System.Windows.Forms)]
       http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx

    (siehe Code-Beispiel) benutzt. Allgemeine Vorgehensweise für Abbrüche in Threads sind ggf. zu berücksichtigen:

    [Abbruch]
    http://msdn.microsoft.com/de-de/library/dd997364.aspx

    Du kannst, wenn eine Exception aufgetreten ist, zum Beispiel ein Signal setzen: [Threading in C# - Part 3 - Using Threads]

    Allgemein ist aber beim Exception-Handling sehr oft der empfehlenswerte Weg, die Exception einfach nicht zu behandeln. Der Aufrufer hat dann eben einen globalen Handler und kann anhand der Exception (oder anderer global gesetzter Status-Infos) normal alles notwendige feststellen und ggf. in eine gewünschte Methode neu einhaken.

    Ein speziellerer Rat könnte kommen, wenn Du den Applikations-Typ und die benutzte .NET Framework Version nennen würdest, aber in der Regel gilt das von mir hier gesagte.


    ciao Frank
    Donnerstag, 2. September 2010 15:28
  • Hallo Marcel,

    vielleicht gleich am Anfang präzisiert: "nicht behandeln" kannst Du im Kontext dieser Frage als "nicht im Thread behandeln" verstehen. Trotzdem kann es sinvolles catch'ing im Thread geben (also nicht dogmatisch sehen).

         > 1. Wozu soll ein *globaler* Handler von Exceptions gut sein (außer logging, information hiding und dergleichen)?
         > 2. Wie kann man denn sinvoll eine unbehandelte Ausnahme behandeln, die sich auf einem fremden Thread
         >     ereignet hat?
         > 3. Würdest Du Ausnahmen abfangen, die man nicht behandeln kann?
         > 4. Application.ThreadException ist nur hilfreich bei Ausnahmen auf dem Haupt-UI-Thread, soviel ich weiß. Oder?


    zu 1)
    Gerade für den Zweck des Fangens von Exceptions in Threads, es ist einfacher (kein Synchronisation-Code notwendig), stabiler, sauberer, an einem Platz. Das sind auch nicht nur "meine" Empfehlungen. Es ist auch nicht ausschliesslich gemeint, wenn explizit gewartet werden soll kann, man auch mal "Thread.IsAlive" pollen, oder über zusätzlich implementierte Event-Signalisierung arbeiten. Aber in der Regel ist es um Längen einfacher und evolvierbarer, über globale Exception-Handler zu gehen. 
    Du hast wahrscheinlich auch nicht so ganz den folgenden von mir oben geposteteten Artikel gelesen, ansonsten kann ich mir Deine Frage (4) nicht so richtig vorstellen:   

    [Application.ThreadException-Ereignis (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx
    (siehe Code-Beispiel)



    zu 2)
    das wurde schon beschrieben, durch globale Status-Informationen kann entweder in ein dafür vorgesehenen Programm-Pfad gewechselt werden, oder wenn festgestellt wird, dass die Anwendung nicht mehr weitergeführt werden kann, dem User ein sauber professioneller Hinweis gegeben werden kann. Die Zeiten von wilden .NET-Message-Boxen wie "Unhandled Exception occured ... " in einer professionellen App sollten langsam vorbei sein ;-)
    Aber Achtung: "Dont use Exceptions to control flow". Also bitte nur in wirklichen ~seltenen Ausnahmefällen.


    zu 3)
    ich vermute, da liegt ein falsches Verständnis von UnhandledException bei Dir vor. Das bedeutet nur, dass diese Ausnahme nicht abgefangen wurde. Man behandelt normal solche UnhandledExceptions sowieso, da sonst sehr unschöne "Unhandled Exception occured ... "  Meldungen einen sehr unprofessionellen Eindruck mache und auch der Admin später etwa im Ereignislog die relevanten Informationen zu sehen bekommt.

        
    zu 4)
    die ThreadException-Behandlung ist immer im Kontext mit den anderen Maßnahmen zu sehen, die ich schon im Beispiel:

    [Application.ThreadException-Ereignis (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx
    (siehe Code-Beispiel)

    angeführt habe. Ich denke, dort ist alles verständlich erklärt und wann was benutzt wird.
    Vielleicht lies Du da nochmal durch, um meine Antwort zu verstehen. Ein Auszug:

    • Fangen Sie Ausnahmen in Threads, die nicht mit Windows Forms erstellt wurden und nicht im Besitz von Windows Forms sind, mit dem UnhandledException-Ereignishandler ab. 

     


    ciao Frank

    Donnerstag, 2. September 2010 19:15
  • Hallo Andre

    Ein solches 'fangen' von Thread zu Thread gibt es nicht explizit/direkt (weil Exceptions primär zu einem Thread-Kontext gehören), sondern es läuft eher auf eine Art 'weiterleiten' hinaus.

    Sowas gibt es 'gratis' etwa bei der 'komfortablen' Verpackung für einen Thread, der Background-Worker  - Komponente (tendenziell eher GUI-Umfeld),
    mittels RunWorkerCompletedEventArgs und 'Error' Eigenschaft:
    http://msdn.microsoft.com/de-de/library/system.componentmodel.backgroundworker.dowork.aspx

    Oder auf eine anderer Art auch, bei den 4.0 Tasks
    http://msdn.microsoft.com/de-de/library/dd997415.aspx

    Ansonst musst du wohl selber wie für jede (wie auch bei Daten) Inter-Thread-Kommunikation (bzw IPC) etwas bauen,
    wobei dein 'Haupt'-Thread gegenseitig auch entsprechende Mechanismen bedienen muss!
       (nur zB, ManualResetEvent uva, oder im GUI-Umfeld die Invoke-Ansätze)

    Als allerletzte Varianten bleiben ja uU AppDomain.UnhandledException (bzw Application.ThreadException / Application.DispatcherUnhandledException)

    Details
    http://msdn.microsoft.com/en-us/library/ms228965.aspx
    http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

    http://stackoverflow.com/questions/188977/catching-exceptions-from-another-thread
    Donnerstag, 2. September 2010 14:37

Alle Antworten

  • Hallo Andre

    Ein solches 'fangen' von Thread zu Thread gibt es nicht explizit/direkt (weil Exceptions primär zu einem Thread-Kontext gehören), sondern es läuft eher auf eine Art 'weiterleiten' hinaus.

    Sowas gibt es 'gratis' etwa bei der 'komfortablen' Verpackung für einen Thread, der Background-Worker  - Komponente (tendenziell eher GUI-Umfeld),
    mittels RunWorkerCompletedEventArgs und 'Error' Eigenschaft:
    http://msdn.microsoft.com/de-de/library/system.componentmodel.backgroundworker.dowork.aspx

    Oder auf eine anderer Art auch, bei den 4.0 Tasks
    http://msdn.microsoft.com/de-de/library/dd997415.aspx

    Ansonst musst du wohl selber wie für jede (wie auch bei Daten) Inter-Thread-Kommunikation (bzw IPC) etwas bauen,
    wobei dein 'Haupt'-Thread gegenseitig auch entsprechende Mechanismen bedienen muss!
       (nur zB, ManualResetEvent uva, oder im GUI-Umfeld die Invoke-Ansätze)

    Als allerletzte Varianten bleiben ja uU AppDomain.UnhandledException (bzw Application.ThreadException / Application.DispatcherUnhandledException)

    Details
    http://msdn.microsoft.com/en-us/library/ms228965.aspx
    http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

    http://stackoverflow.com/questions/188977/catching-exceptions-from-another-thread
    Donnerstag, 2. September 2010 14:37
  • Hallo HP.,

    da das je nach Applikations-Typ unterschiedlich implementiert wird, müsste ich Dir die Frage nach dem App-Typ stellen (ASP.NET/WinFormWPF/Silverlight) 

    Trotzdem gebe ich Dir schon mal den Rat, dass es oft sinnvoll ist, das über ein globales Abfangen der Exception zu machen.
    Das haben wir immer recht vorteilhaft einsetzen können. Hier Beispiele/Hinweise: [global exception Handling C# - Google-Suche].
    Unter WinForms habe ich meist das Verfahren:

       [Application.ThreadException-Ereignis (System.Windows.Forms)]
       http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx

    (siehe Code-Beispiel) benutzt. Allgemeine Vorgehensweise für Abbrüche in Threads sind ggf. zu berücksichtigen:

    [Abbruch]
    http://msdn.microsoft.com/de-de/library/dd997364.aspx

    Du kannst, wenn eine Exception aufgetreten ist, zum Beispiel ein Signal setzen: [Threading in C# - Part 3 - Using Threads]

    Allgemein ist aber beim Exception-Handling sehr oft der empfehlenswerte Weg, die Exception einfach nicht zu behandeln. Der Aufrufer hat dann eben einen globalen Handler und kann anhand der Exception (oder anderer global gesetzter Status-Infos) normal alles notwendige feststellen und ggf. in eine gewünschte Methode neu einhaken.

    Ein speziellerer Rat könnte kommen, wenn Du den Applikations-Typ und die benutzte .NET Framework Version nennen würdest, aber in der Regel gilt das von mir hier gesagte.


    ciao Frank
    Donnerstag, 2. September 2010 15:28
  • Hallo Frank,

    Deine Empfehlungen machen mich etwas stutzig. Ich frage also lieber erstmal nach.

    1. Wozu soll ein *globaler* Handler von Exceptions gut sein (außer logging, information hiding und dergleichen)?
    2. Wie kann man denn sinvoll eine unbehandelte Ausnahme behandeln, die sich auf einem fremden Thread ereignet hat?
    3. Würdest Du Ausnahmen abfangen, die man nicht behandeln kann?
    4. Application.ThreadException ist nur hilfreich bei Ausnahmen auf dem Haupt-UI-Thread, soviel ich weiß. Oder?

    Die Empfehlung, Exceptions, die man nicht behandeln kann, nicht zu fangen, kann ich gut verstehen. Auch ich bin ein großer Fan von fail fast.

    Gruß
    Marcel

    Donnerstag, 2. September 2010 18:17
  • Hallo Marcel,

    vielleicht gleich am Anfang präzisiert: "nicht behandeln" kannst Du im Kontext dieser Frage als "nicht im Thread behandeln" verstehen. Trotzdem kann es sinvolles catch'ing im Thread geben (also nicht dogmatisch sehen).

         > 1. Wozu soll ein *globaler* Handler von Exceptions gut sein (außer logging, information hiding und dergleichen)?
         > 2. Wie kann man denn sinvoll eine unbehandelte Ausnahme behandeln, die sich auf einem fremden Thread
         >     ereignet hat?
         > 3. Würdest Du Ausnahmen abfangen, die man nicht behandeln kann?
         > 4. Application.ThreadException ist nur hilfreich bei Ausnahmen auf dem Haupt-UI-Thread, soviel ich weiß. Oder?


    zu 1)
    Gerade für den Zweck des Fangens von Exceptions in Threads, es ist einfacher (kein Synchronisation-Code notwendig), stabiler, sauberer, an einem Platz. Das sind auch nicht nur "meine" Empfehlungen. Es ist auch nicht ausschliesslich gemeint, wenn explizit gewartet werden soll kann, man auch mal "Thread.IsAlive" pollen, oder über zusätzlich implementierte Event-Signalisierung arbeiten. Aber in der Regel ist es um Längen einfacher und evolvierbarer, über globale Exception-Handler zu gehen. 
    Du hast wahrscheinlich auch nicht so ganz den folgenden von mir oben geposteteten Artikel gelesen, ansonsten kann ich mir Deine Frage (4) nicht so richtig vorstellen:   

    [Application.ThreadException-Ereignis (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx
    (siehe Code-Beispiel)



    zu 2)
    das wurde schon beschrieben, durch globale Status-Informationen kann entweder in ein dafür vorgesehenen Programm-Pfad gewechselt werden, oder wenn festgestellt wird, dass die Anwendung nicht mehr weitergeführt werden kann, dem User ein sauber professioneller Hinweis gegeben werden kann. Die Zeiten von wilden .NET-Message-Boxen wie "Unhandled Exception occured ... " in einer professionellen App sollten langsam vorbei sein ;-)
    Aber Achtung: "Dont use Exceptions to control flow". Also bitte nur in wirklichen ~seltenen Ausnahmefällen.


    zu 3)
    ich vermute, da liegt ein falsches Verständnis von UnhandledException bei Dir vor. Das bedeutet nur, dass diese Ausnahme nicht abgefangen wurde. Man behandelt normal solche UnhandledExceptions sowieso, da sonst sehr unschöne "Unhandled Exception occured ... "  Meldungen einen sehr unprofessionellen Eindruck mache und auch der Admin später etwa im Ereignislog die relevanten Informationen zu sehen bekommt.

        
    zu 4)
    die ThreadException-Behandlung ist immer im Kontext mit den anderen Maßnahmen zu sehen, die ich schon im Beispiel:

    [Application.ThreadException-Ereignis (System.Windows.Forms)]
    http://msdn.microsoft.com/de-de/library/system.windows.forms.application.threadexception.aspx
    (siehe Code-Beispiel)

    angeführt habe. Ich denke, dort ist alles verständlich erklärt und wann was benutzt wird.
    Vielleicht lies Du da nochmal durch, um meine Antwort zu verstehen. Ein Auszug:

    • Fangen Sie Ausnahmen in Threads, die nicht mit Windows Forms erstellt wurden und nicht im Besitz von Windows Forms sind, mit dem UnhandledException-Ereignishandler ab. 

     


    ciao Frank

    Donnerstag, 2. September 2010 19:15
  • Ich bin sprachlos.

    Marcel

    Donnerstag, 2. September 2010 19:24