2009-07-30 7 views
13

Mam aplikację WinForm. Informacje zaczynają się od pliku Program.cs, gdzie mamy zdefiniowany main(). Umieściłem ten kod w bloku try-catch.Dlaczego wyjątek win32 nie jest przechwytywany przez mechanizm obsługi wyjątków 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()); 
      } 
     } 
    } 

Gdy istnieje wyjątek win32, mechanizm ten nie powiedzie się i komunikat nieobsługiwany wyjątek i awarie aplikacji.
Mam 2 pytania dotyczące tego kodu:

1) Dlaczego wyjątki win32 nie zostały złapane.

2) Czy dobrą praktyką jest wychwytywanie wyjątków na najwyższym poziomie.

+0

Wow, nigdy tak naprawdę nie myślałem o tym, dobre pytanie i dobre odpowiedzi :) – leppie

+0

Proszę również skomentować drugie pytanie. – Rohit

+0

Może mógłbyś zrobić to drugie pytanie SO ;-) – Mac

Odpowiedz

12

EDIT: jako Pratik, następująca odpowiedź dotyczy tylko .NET 1.0 i .NET 1.1. Począwszy od .NET 2.0, wyjątek inny niż CLS powinien zostać przechwycony jako RuntimeWrappedException.


Wyjątki Win32 nie pochodzą z klasy .NET Exception. Spróbuj:

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

Zobacz Catch non-CLSCompliant exceptions in general handlers aby uzyskać więcej informacji.

+4

To nie jest wymagane w .Net 2.0 domyślnie. Wszystkie wyjątki bez CLS są zgrupowane jako wyjątek RuntimeWrappedException. Zobacz http://msdn.microsoft.com/en-us/library/ms404228.aspx – softveda

+0

Win32Exception

+0

@Pratik: dzięki za link. @ Tommy Carlier: cf. Łącze Pratika ... – Mac

0

może trzeba złapać jak Win32Exception (lub ExternalException) zamiast

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

wydaje mi się, że Win32Exception dziedziczy ExternalException ale ExternalException nie dziedziczy z Exception tak nie zostanie złapany przez kod .

Edytuj: Zobacz inne odpowiedzi, dlaczego tak się nie stało!

Edit 2: Co do drugiej części, jak stwierdził AnthonyWJones To dobre maniery, aby poinformować użytkownika, że ​​problem spowodowała aplikacja do zamknięcia, jednak polecam przy użyciu zwykłego oświadczenia angielskiego dla użytkownika i rejestrowanie stosu wyjątków w pliku dziennika na własny użytek.

+1

Oba te są pochodne od wyjątków, dlatego na powierzchni tego problemu powinien zadziałać połów w pytaniu. Dlaczego nie widzę mojej odpowiedzi. – AnthonyWJones

3

Wykonanie Application.Run nie powoduje błędu. Dzieje się to w innym wątku (lub przynajmniej asynchronicznie).

Dobrym pomysłem jest poinformowanie użytkownika w przyjazny sposób, że aplikacja zawiodła, zanim zniknie całkowicie, jednak nie jest to dobry pomysł, aby po prostu złapać, a następnie kontynuować.

3

Chociaż nie wiem, dlaczego blok catch nie działa, spróbuj użyć Application ThreadException Event. To powinno wychwycić każdy błąd w wątkach aplikacji. Dodaj procedurę obsługi zdarzeń przed wywołaniem Application.Run.

Dla drugiej odpowiedzi zdecydowanie tak. Opracowuję i utrzymuję aplikację WinForm dla przedsiębiorstw, która rozmawia z zapleczem usług sieciowych na temat wątków działających w tle. Jeśli jakiekolwiek awarie wywołań usług sieciowych obsługują zdarzenie wyjątek threadexception (i także appdomain nieobsługiwanego wyjątku), zaloguj się i wyskakuj o jeden błąd, który użytkownicy biznesowi mogą zgłosić i pozwolić im kontynuować bez awaryjnej aplikacji.

0

1) Wyjątki Win32 powinny zostać przechwycone. Może wyjątek jest wyrzucany z wątku tła lub wątku GC?

2) To zależy od struktury aplikacji. Na przykład, jeśli Twój interfejs powiadomienia o błędzie był w jakiś sposób powiązany z formularzem głównym (np. Musisz wywołać wątek interfejsu użytkownika z wątku roboczego), byłoby głupio wyświetlać interfejs w bloku kodu poza kodem, który uruchamia wiadomość pętla. Jeśli jednak Twój przykładowy kod jest jednowątkowy, będzie w porządku.

1

Spróbuj subskrybowania tych wydarzeń przed swoimi uruchomień aplikacji (Application.Run):

Mogłeś wtedy pozbyć się bloku try catch.


Uważam, że złym rozwiązaniem jest łapanie wyjątków na najwyższym poziomie, ale nie można tego uniknąć! Podczas programowania (debugowania) te wyjątki nie powinny być przechwytywane, a aplikacja powinna robić najgorszą możliwą rzecz (awaria?). W produkcji (Release) będziesz chciał, aby aplikacja uległa jak najdelikatniejszej degradacji nawet wtedy, gdy wystąpią nieobsługiwane wyjątki. Jest to jedno z niewielu zastosowań, które znalazłem dla DEBUG preprocessor variable.

+0

Masz: 2 odpowiedzi w jednym. Którego zamierzasz (lub przeciwko)? – Mac