2009-08-19 16 views
6

Jest to związane z previous question.Dlaczego wyjątki AppDomain niezmiennie kończą aplikację?

Próbuję teraz zrozumieć, w jaki sposób wyjątki wątków interfejsu użytkownika mogą być powstrzymane przed zakończeniem aplikacji, podczas gdy wyjątki inne niż interfejs użytkownika nie mogą być.

Aby uzyskać więcej informacji, zobacz this example.

Najważniejsze, co chciałbym w tym przypadku zrobić, to "cicho" zakończyć proces - bez wyświetlania okna dialogowego Windows, które pyta, czy chcę wysłać raport o błędzie, czy nie.

To mój AppDomain UnhandledExceptionHandler:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{    
    try 
    { 
     // Maybe do some logging here if allowed 
    } 
    catch 
    { 
    } 

    // then just terminate the application 
    Application.Exit();    
} 

UPDATE
W świetle uwag w this answer, chciałbym wyjaśnić, że najważniejsze Chciałbym dowiedzieć się więcej na temat mechanizmu, który umożliwia wątkowi UI wczesną możliwość przechwycenia nieobsługiwanych wyjątków za pośrednictwem mechanizmu Application.ThreadException. I czy takie zachowanie może zostać zaimplementowane w wątku innym niż UI.

Odpowiedz

7

Tak, po jakiejś więcej wyszukiwań w Google znalazłem to bardzo ciekawe wyjaśnienie, że został podany do tego samego problemu w sposób opisany przez Jeff Atwood on his blog.

Witam wszystkich, Przepraszamy za zamieszanie. Takie zachowanie jest w rzeczywistości projektem, chociaż projekt może być czasami nieco zakręcony.

Przede wszystkim należy pamiętać, że zdarzenie UnhandledException nie jest nieobsługiwanym wyjątkiem "handler". Rejestracja na wydarzenie, wbrew temu, co mówi dokumentacja :-(, nie powoduje obsługi nieobsługiwanych wyjątków (Od tego czasu nie będą one nieobsługiwane, ale zatrzymam się już z kołowrotowym rozumowaniem ...) impreza UnhandledException po prostu informacją, że wyjątek upadł nieobsługiwany, w przypadku, gdy chcesz spróbować zapisać stan przed gwintem lub aplikacji umiera. FWIW, złożyli błąd, aby uzyskać docs stałe.

Wystarczy skomplikować rzeczy, w wersji 1.0 i 1.1, nieobsługiwany wyjątek nie zawsze oznaczał, że twoja aplikacja umrze. Jeśli nieobsługiwany wyjątek wystąpił w cokolwiek innego niż główny wątek lub wątek, który rozpoczął życie w kodzie niezarządzanym, środowisko CLR zjadło wyjątek i zezwoliło aplikacji na kontynuowanie działania. Było to na ogół złe, ponieważ często zdarzało się, że wątki ThreadPool cichutko wymierały, jeden po drugim, dopóki twoja aplikacja nie wykonywała żadnej pracy. Ustalenie przyczyny tego rodzaju awarii było prawie niemożliwe. Być może dlatego Jeff pomyślał, że to zadziałało ... po prostu zawsze widział awarie na wątkach innych niż główne.

W wersji 2.0, nieobsługiwany wyjątek w dowolnym wątku spowoduje usunięcie aplikacji. Odkryliśmy, że znacznie łatwiej jest debugować awarie, niż debugować zawieszanie lub opisany wcześniej problem dotyczący cichego zatrzymania pracy.

BTW, na moim komputerze 1.1 przykład z MSDN ma oczekiwane wyjście; po prostu druga linia pojawia się dopiero po podłączeniu debuggera (lub nie). W wersji v2 odwróciliśmy wszystko, aby zdarzenie UnhandledException wystrzeliło przed dołączeniem debuggera, co wydaje się być tym, czego większość ludzi się spodziewa.

Jonathan Keljo CLR wyjątkami PM Jonathan Keljo 18 lutego 2005 22:02

Jednak nadal jestem zainteresowany jak wątek UI realizuje trik pozwala mieć zaczep -all handler dla wszystkich wyjątków wątku interfejsu użytkownika.

Nawet więcej, Jestem bardzo zainteresowany w taki sposób, aby wyłączyć debugowanie Dialog .NET JIT dla mojej aplikacji tylko (bez disabling it for the whole machine as seen here)

3

To nie jest tak, że jakikolwiek wyjątek AppDomain kończy aplikację, to że nieobsługiwane wyjątki (jakiegokolwiek rodzaju) zerwą AppDomain i zamkną aplikację.

Problem polega na tym, że można obsługiwać wyjątki wątku interfejsu użytkownika jawnie, na dość wysokim poziomie. Jednak, gdy masz nieobsługiwany wyjątek w wątku w tle, nie ma możliwości łatwego poruszania się na tym samym poziomie, więc ma tendencję do propagowania i ściągania aplikacji. Application.ThreadException pozwala ci przynajmniej wiedzieć, że to jest przyczyną błędu i zalogować się, jeśli to konieczne.

Nieobsługiwane wyjątki w wątku interfejsu użytkownika powodują to samo.

+0

@Reed: „Nieobsługiwany wyjątki w wątku UI spowoduje takie same coś się wydarzy. " - to nie jest prawda. Utwórz aplikację testową i wypróbuj ją sam. –

+1

Technicznie powinienem był powiedzieć "Nieobsługiwane wyjątki w głównym wątku". Windows Forms dodaje własne zachowanie wyjątku w wątku UI (ponieważ działa całkowicie w wątku UI), który zmienia zachowanie głównego wątku. Stwórz aplikację konsolową i spróbuj tego, a zobaczysz, że nie ma znaczenia, co robią wątki - wszystko to zniszczy aplikację. –

+0

Następnie powinienem powtórzyć moje pytanie: W jaki sposób wątek interfejsu użytkownika wykonuje jego ogólne zachowanie podczas obsługi wyjątków? Czy jest to coś, co mogę replikować jako zachowanie dla wątku innego niż UI? –

2

Czy to w ogóle pomaga?

Improved Unhandled Exception behavior in .NET 2.0

Również ten kod wydaje się "umrzeć spokojnie". Szukasz czegoś innego?

using System; 

namespace UnhandledException 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; 

      throw new NotImplementedException(); 
     } 

     static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 
     { 
      Exception exception = (Exception)e.ExceptionObject; 
      System.Console.WriteLine("exception=[" + exception.ToString() + "]"); 

      Environment.Exit(-1); 
     } 
    } 
} 
+0

Tak, to prawda. Właśnie skończyłem czytać post i komentarze, kiedy to opublikowałeś. +1 jednak .. –

+0

Tak, Environemnt.Exit chyba załatwi sprawę! Zostawę pytania otwarte na chwilę, aby sprawdzić, czy wątek interfejsu użytkownika umożliwia wyjątek typu catch-all. W przeciwnym razie będziesz miał głos na zaakceptowaną odpowiedź! –

+0

Application.ThreadException to kolejny wariant "nieobsługiwanego sterownika wyjątków". Istnieje wiele wariantów (Console App vs. WinForms vs. WebForms vs. WCF itd.). Nie jestem pewien, czy rozumiem twoje pytanie. Generalnie wdrażam każdy, który ma zastosowanie. –

Powiązane problemy