Programing

.NET- "모든 예외 처리기 잡기"를 구현하는 가장 좋은 방법은 무엇입니까?

lottogame 2020. 10. 20. 07:12
반응형

.NET- "모든 예외 처리기 잡기"를 구현하는 가장 좋은 방법은 무엇입니까?


"다른 모든 것이 실패하면"잡는 것이 가장 좋은 방법이 무엇인지 궁금합니다.

즉, 애플리케이션에서 가능한 한 많은 예외를 처리하고 있지만 여전히 버그가있을 수 있으므로 처리되지 않은 모든 예외를 포착하는 무언가가 있어야 정보를 수집하고 데이터베이스에 저장하거나 제출할 수 있습니다. 웹 서비스에.

AppDomain.CurrentDomain.UnhandledException 이벤트가 모든 것을 캡처합니까? 애플리케이션이 다중 스레드 인 경우에도?

참고 : Windows Vista는 충돌 후 모든 응용 프로그램이 자체적으로 복구 할 수 있도록하는 기본 API 기능을 제공합니다. 지금은 이름을 생각할 수 없지만 많은 사용자가 여전히 사용하고 있으므로 사용하지 않는 것이 좋습니다. 윈도우 XP.


방금 AppDomain의 UnhandledException 동작을 사용했습니다 (이는 처리되지 않은 예외가 등록 된 마지막 단계입니다).

예, 이벤트 처리기를 처리 한 후 응용 프로그램이 종료되고 불쾌한 "... 프로그램이 작동을 중지했습니다."라는 메시지가 표시됩니다.

:) 당신은 여전히 그것을 피할 수 있습니다.

확인 :

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

추신 : 처리되지 않은 Application.ThreadException (WinForms) 또는 DispatcherUnhandledException (WPF)을 상위 수준에서 처리합니다.


ASP.NET에서는 파일 Application_Error함수 를 사용 Global.asax합니다.

윈폼에서, 당신은을 사용 MyApplication_UnhandledExceptionApplicationEvents파일

코드에서 처리되지 않은 예외가 발생하면이 두 함수가 모두 호출됩니다. 예외를 기록하고 이러한 함수에서 사용자에게 멋진 메시지를 표시 할 수 있습니다.


Winform 응용 프로그램의 경우 AppDomain.CurrentDomain.UnhandledException 외에도 Application.ThreadExceptionApplication.SetUnhandledExceptionMode (w / UnhandledExceptionMode.CatchException)를 사용합니다. 이 조합은 모든 것을 잡는 것 같습니다.


메인 스레드에는 다음과 같은 옵션이 있습니다.

다른 스레드의 경우 :

  • 보조 스레드에는 처리되지 않은 예외가 없습니다. SafeThread 사용
  • 작업자 스레드 : (타이머, 스레드 풀) 안전망이 전혀 없습니다!

이러한 이벤트는 예외를 처리 하지 않고 단지 응용 프로그램에 보고 할 뿐이 라는 점을 염두에 두십시오. 종종 유용한 / 정상적인 작업을 수행하기에는 너무 늦었을 때입니다.

예외를 기록하는 것은 좋지만 응용 프로그램을 모니터링하는 것이 더 좋습니다 ;-)

주의 사항 : 저는 SafeThread 기사 의 저자입니다 .


WinForms의 경우 현재 스레드의 처리되지 않은 예외 이벤트에도 연결하는 것을 잊지 마십시오 (특히 다중 스레딩을 사용하는 경우).

여기여기여기 에 모범 사례에 대한 일부 링크 (아마도 .net에 대한 최상의 예외 처리 문서)


웹 응용 프로그램에서 발생하는 모든 ASP.NET 오류를 기록하는 ELMAH 라는 멋진 기능도 있습니다. 나는 당신이 Winform 앱 솔루션에 대해 질문하고 있다는 것을 알고 있지만 이것이 웹 앱에서 이러한 유형의 것을 필요로하는 모든 사람에게 도움이 될 수 있다고 생각했습니다. 우리는 제가 일하는 곳에서 사용하고 디버깅에 매우 도움이되었습니다 (특히 프로덕션 서버에서!)

여기에 몇 가지 기능이 있습니다 (페이지에서 바로 가져옴).

  • 거의 모든 처리되지 않은 예외 로깅.
  • 레코딩 된 예외의 전체 로그를 원격으로 볼 수있는 웹 페이지입니다.
  • 기록 된 예외의 전체 세부 정보를 원격으로 볼 수있는 웹 페이지입니다.
  • 대부분의 경우 customErrors 모드가 꺼져 있어도 ASP.NET이 특정 예외에 대해 생성 한 노란색 죽음의 원래 화면을 검토 할 수 있습니다.
  • 오류 발생시 각 오류에 대한 이메일 알림.
  • 로그에서 최근 15 개 오류에 대한 RSS 피드입니다.
  • 인 메모리, Microsoft SQL Server 및 커뮤니티에서 기여한 몇 가지를 포함하여 로그에 대한 여러 백업 저장소 구현.

You can monitor most exceptions in that handler even in multithreaded apps, but .NET (starting with 2.0) won't allow you to cancel unhandled exceptions unless you enable the 1.1 compatibility mode. When that happens the AppDomain will be shut down no matter what. The best you could do is launch the app in a different AppDomain so that you can handle this exception and create a new AppDomain to restart the app.


I am using the following approach, which works and reduces greatly the amount of code ( yet I am not sure if there is a better way or what the pitfalls of it might be. Whenever you call: I quess the quys giving minuses would be polite enough to clarify their actions ; )

try 
{
    CallTheCodeThatMightThrowException()
 }
catch (Exception ex)
{
    System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
    Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch

And here is the ErrorHandler code : Just to make clear- : objUser - is the object modelling the appusers ( you might get info such as domain name , department , region etc. for logging purposes ILog logger - is the logging object - e.g. the one performing the logging activities StackTrace st - the StackTrace object giving you debugging info for your app

using System;
using log4net; //or another logging platform

namespace GenApp.Utils
{
  public class ErrorHandler
  {
    public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
    {
      if (ex is NullReferenceException)
      { 
      //do stuff for this ex type
      } //eof if

      if (ex is System.InvalidOperationException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.IndexOutOfRangeException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.Data.SqlClient.SqlException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.FormatException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is Exception)
      {
        //do stuff for this ex type
      } //eof catch

    } //eof method 

  }//eof class 
} //eof namesp

In a manged GUI app, by default, exceptions that originate in the GUI thread are handled by whatever is assigned to the Application.ThreadException.

Exceptions that originate in the other threads are handled by AppDomain.CurrentDomain.UnhandledException.

If you want your GUI thread exceptions to work just like your-non GUI ones, so that they get handled by AppDomain.CurrentDomain.UnhandledException, you can do this:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

An advantage to catching the GUI thread exceptions using ThreadException is that you can give the use the options of letting the app continue. To make sure no config files are overriding default behavior, you can call:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

You are still vulnerable to exceptions from badly behaved native dlls. If a native dll installs its own handler using Win32 SetUnhandledExceptionFilter, it is supposed to save the pointer to the previous filter and call it too. If it doesn't do that, your handler wont' get called.

참고URL : https://stackoverflow.com/questions/219594/net-whats-the-best-way-to-implement-a-catch-all-exceptions-handler

반응형