질문 : 콘솔 응용 프로그램에서 처리되지 않은 예외에 대한 전역 예외 처리기를 정의하고 싶습니다. asp.net에서 global.asax와 Windows 응용 프로그램 / 서비스에서 하나를 정의 할 수 있으며 다음과 같이 정의 할 수 있습니다
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler);
그러나 콘솔 응용 프로그램에 대한 전역 예외 처리기를 어떻게 정의 할 수 있습니까?
currentDomain이 작동하지 않는 것 같습니다 (.NET 2.0)?
편집하다:
아, 바보 같은 실수.
VB.NET에서 currentDomain 앞에 “AddHandler”키워드를 추가해야합니다. 그렇지 않으면 IntelliSense에서 UnhandledException 이벤트가 표시되지 않습니다
. VB.NET과 C # 컴파일러가 이벤트 처리를 다르게 처리하기 때문입니다.
답변
아니요, 올바른 방법입니다. 이것은 당신이 아마 일할 수있는 것만 큼 정확하게 작동했습니다 :
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);
}
}
이러한 방식으로 지터에 의해 생성 된 유형 및 파일로드 예외를 포착 할 수 없습니다. Main () 메서드가 실행되기 전에 발생합니다. 지터 지연을 필요로하는 위험을 감수하고 위험한 코드를 다른 방법으로 옮기고 [MethodImpl (MethodImplOptions.NoInlining)] 속성을 적용하십시오.
답변
단일 스레드 응용 프로그램이있는 경우 Main 함수에서 간단한 try / catch를 사용할 수 있지만 Main 함수 외부에서 발생할 수있는 예외 (예 : 다른 스레드에서 언급 된 것처럼)는 다루지 않습니다. 코멘트). 이 코드는 Main에서 처리하려고 했는데도 예외로 인해 응용 프로그램이 종료 될 수있는 방법을 보여줍니다 (Enter를 누르고 예외가 발생하기 전에 응용 프로그램이 정상적으로 종료되도록 허용하는 경우 프로그램이 정상적으로 종료되는 방법에 주목하지만 실행을 허용 한 경우) , 그것은 불행하게 종료됩니다) :
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;
}
}
응용 프로그램이 종료되기 전에 정리를 수행하기 위해 다른 스레드에서 예외가 발생하는 경우 알림을받을 수 있지만, 내가 알 수있는 한 콘솔 응용 프로그램에서 예외를 처리하지 않으면 응용 프로그램을 계속 강제 실행할 수 없습니다 응용 프로그램이 .NET 1.x에서와 같이 동작하도록하기 위해 모호한 호환성 옵션을 사용하지 않고 발생하는 스레드에서 이 코드는 주 스레드에 다른 스레드에서 발생하는 예외를 통지하는 방법을 보여 주지만 여전히 행복하게 종료됩니다.
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;
}
}
따라서 콘솔 응용 프로그램에서 처리하는 가장 깨끗한 방법 은 모든 스레드에 루트 수준의 예외 처리기가 있는지 확인하는 것입니다.
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");
}
}
답변
또한 스레드의 예외를 처리해야합니다.
static void Main(string[] args) {
Application.ThreadException += MYThreadHandler;
}
private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
{
Console.WriteLine(e.Exception.StackTrace);
}
Whoop, 죄송합니다. winforms, 콘솔 응용 프로그램에서 사용하는 모든 스레드에 대해 try / catch 블록으로 묶어야합니다. 처리되지 않은 예외가 발생하는 백그라운드 스레드는 응용 프로그램을 종료시키지 않습니다.
답변
방금 이전 VB.NET 콘솔 응용 프로그램을 상속했으며 전역 예외 처리기를 설정해야했습니다. 이 질문은 VB.NET을 몇 번 언급하고 VB.NET으로 태그가 지정되어 있지만 여기에있는 다른 모든 대답은 C #에 있으므로 VB.NET 응용 프로그램의 정확한 구문을 추가 할 것이라고 생각했습니다.
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
REM
Stack Overflow가 구문 강조를 조금 더 잘 처리하는 것처럼 보이므로 작은 따옴표 대신 주석 표시를 사용했습니다 REM
.
답변
.Net 2.0 용 MSDN 문서에 따라 노력하고 있습니다. 콘솔 앱의 진입 점을 중심으로 try / catch를 시도해 볼 수도 있습니다.
static void Main(string[] args)
{
try
{
// Start Working
}
catch (Exception ex)
{
// Output/Log Exception
}
finally
{
// Clean Up If Needed
}
}
그리고 이제 캐치가 잡히지 않은 것을 처리 합니다 (메인 스레드에서 ). 우아하고 원할 때 다시 시작하거나 앱을 죽이고 예외를 기록 할 수 있습니다. 정리하고 싶다면 마지막으로 추가하십시오. 각 스레드는 메인과 유사한 고유 한 예외 처리가 필요합니다.
BlueMonkMN에 의해 지적되고 그의 답변에 자세히 표시된 스레드에 대한 요점을 명확히하기 위해 편집되었습니다.