Globalna obsługa wyjątków. NET w aplikacji konsolowej

Pytanie: chcę zdefiniować globalną obsługę wyjątków dla nieobsługiwanych wyjątków w mojej aplikacji konsolowej. W asp.net, można zdefiniować jeden w globalnym.asax, a w aplikacjach /usługach windows można zdefiniować jak poniżej

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

Ale jak Mogę zdefiniować globalną obsługę wyjątków dla aplikacji konsolowej ?
currentDomain wydaje się nie działać (. NET 2.0) ?

Edytuj:

Głupi błąd.
W VB.NET, trzeba dodać Słowo kluczowe "AddHandler" przed currentDomain, w przeciwnym razie nie widać zdarzenia UnhandledException w IntelliSense...
To dlatego, że VB.NET a kompilatory C# traktują obsługę zdarzeń inaczej.
Author: spinodal, 2010-06-28

5 answers

Nie, to właściwy sposób. To działało dokładnie tak, jak powinno, coś z czego możesz pracować być może:

using System;

class Program {
    static void Main(string[] args) {
        System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
        throw new Exception("Kaboom");
    }

    static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) {
        Console.WriteLine(e.ExceptionObject.ToString());
        Console.WriteLine("Press Enter to continue");
        Console.ReadLine();
        Environment.Exit(1);
    }
}

Należy pamiętać, że w ten sposób nie można wychwycić WYJĄTKÓW typu i obciążenia plików generowanych przez jitter. Dzieje się to zanim twoja metoda Main () zacznie działać. Wyłapywanie ich wymaga opóźnienia jittera, przeniesienia ryzykownego kodu do innej metody i zastosowania [MethodImpl (MethodImplOptions.NoInlining)]

 288
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-29 14:05:44

Jeśli masz aplikację jednowątkową, możesz użyć prostego try/catch w głównej funkcji, jednak nie obejmuje to wyjątków, które mogą być wyrzucane poza główną funkcję, na przykład w innych wątkach (jak wspomniano w innych komentarzach). Ten kod pokazuje, jak wyjątek może spowodować zakończenie aplikacji, nawet jeśli próbowałeś go obsłużyć W Main (zauważ, jak program zakończy się z wdziękiem, jeśli naciśniesz klawisz enter i pozwolisz aplikacji zakończyć się z wdziękiem przed wyjątek występuje, ale jeśli pozwolisz mu działać, kończy się dość nieszczęśliwie):

static bool exiting = false;

static void Main(string[] args)
{
   try
   {
      System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
      demo.Start();
      Console.ReadLine();
      exiting = true;
   }
   catch (Exception ex)
   {
      Console.WriteLine("Caught an exception");
   }
}

static void DemoThread()
{
   for(int i = 5; i >= 0; i--)
   {
      Console.Write("24/{0} =", i);
      Console.Out.Flush();
      Console.WriteLine("{0}", 24 / i);
      System.Threading.Thread.Sleep(1000);
      if (exiting) return;
   }
}

Możesz otrzymać powiadomienie o tym, kiedy inny wątek rzuca wyjątek, aby wykonać pewne oczyszczenie przed zakończeniem działania aplikacji, ale z tego, co wiem, nie możesz, z aplikacji konsolowej, zmusić aplikacji do dalszego działania, jeśli nie obsłużysz wyjątku w wątku, z którego został wyrzucony, bez użycia pewnych niejasnych opcji kompatybilności, aby aplikacja zachowywała się tak, jakby miała inny wątek. z. NET 1.x. Ten kod pokazuje, w jaki sposób główny wątek może być powiadamiany o wyjątkach pochodzących z innych wątków, ale i tak zakończy się nieszczęśliwie:

static bool exiting = false;

static void Main(string[] args)
{
   try
   {
      System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
      AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
      demo.Start();
      Console.ReadLine();
      exiting = true;
   }
   catch (Exception ex)
   {
      Console.WriteLine("Caught an exception");
   }
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
   Console.WriteLine("Notified of a thread exception... application is terminating.");
}

static void DemoThread()
{
   for(int i = 5; i >= 0; i--)
   {
      Console.Write("24/{0} =", i);
      Console.Out.Flush();
      Console.WriteLine("{0}", 24 / i);
      System.Threading.Thread.Sleep(1000);
      if (exiting) return;
   }
}

Więc moim zdaniem, najczystszym sposobem obsługi tego w aplikacji konsolowej jest upewnienie się, że każdy wątek ma obsługę wyjątków na poziomie głównym:

static bool exiting = false;

static void Main(string[] args)
{
   try
   {
      System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
      demo.Start();
      Console.ReadLine();
      exiting = true;
   }
   catch (Exception ex)
   {
      Console.WriteLine("Caught an exception");
   }
}

static void DemoThread()
{
   try
   {
      for (int i = 5; i >= 0; i--)
      {
         Console.Write("24/{0} =", i);
         Console.Out.Flush();
         Console.WriteLine("{0}", 24 / i);
         System.Threading.Thread.Sleep(1000);
         if (exiting) return;
      }
   }
   catch (Exception ex)
   {
      Console.WriteLine("Caught an exception on the other thread");
   }
}
 23
Author: BlueMonkMN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-29 00:31:15

Musisz również obsługiwać wyjątki z wątków:

static void Main(string[] args) {
Application.ThreadException += MYThreadHandler;
}

private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
{
    Console.WriteLine(e.Exception.StackTrace);
}

Whoop, przepraszam, że to było dla winforms, dla wszystkich wątków, których używasz w aplikacji konsolowej, będziesz musiał zamknąć w bloku try / catch. Wątki tła, które napotykają nieobsługiwane wyjątki, nie powodują zakończenia aplikacji.

 12
Author: BlackICE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 15:31:12

Właśnie odziedziczyłem starą VB.NET aplikacja konsolowa i potrzebne do skonfigurowania globalnego obsługi wyjątków. Ponieważ to pytanie wspomina VB.NET kilka razy i jest oznaczony VB.NET, ale wszystkie inne odpowiedzi są w C#, pomyślałem, że dodam dokładną składnię dla VB.NET aplikacja również.

Public Sub Main()
    REM Set up Global Unhandled Exception Handler.
    AddHandler System.AppDomain.CurrentDomain.UnhandledException, AddressOf MyUnhandledExceptionEvent

    REM Do other stuff
End Sub

Public Sub MyUnhandledExceptionEvent(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
    REM Log Exception here and do whatever else is needed
End Sub

Użyłem znacznika REM comment zamiast pojedynczego cytatu, ponieważ Stack Overflow wydawał się lepiej obsługiwać podświetlanie składni za pomocą REM.

 1
Author: Russell Jonakin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-19 19:58:57

To, co próbujesz, powinno działać zgodnie z dokumentami MSDN dla. Net 2.0. Możesz również spróbować try/catch bezpośrednio w głównym wokół punktu wejścia do aplikacji konsoli.

static void Main(string[] args)
{
    try
    {
        // Start Working
    }
    catch (Exception ex)
    {
        // Output/Log Exception
    }
    finally
    {
        // Clean Up If Needed
    }
}

A teraz twój haczyk poradzi sobie ze wszystkim, co nie zostało złapane ( w głównym wątku ). Może być pełen wdzięku, a nawet uruchom ponownie, jeśli chcesz, lub po prostu pozwól aplikacji umrzeć i zaloguj wyjątek. Dodałbyś wreszcie, gdybyś chciał coś posprzątać. każdy wątek będzie wymagał własnego wysokiego poziomu obsługa wyjątków podobna do głównej.

edytowane, aby wyjaśnić punkt dotyczący wątków, jak wskazał BlueMonkMN i szczegółowo pokazał w swojej odpowiedzi.

 -13
Author: Rodney S. Foley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-29 23:42:25