全局错误捕获,以防止运行时异常导致程序崩溃

问题描述

我创建了一个在客户端之间发送数据的程序,一旦发生运行时异常,整个程序就会退出

我想为所有运行时异常创建一个全局捕获器,这样我的程序就不会在发生运行时异常时退出。发生异常时,程序退出显示以下消息:

Process finished with exit code -532,462,766.

这是我的错误堆栈的简化视图:

Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.InvalidDataException: Found invalid data while decoding.
   at Game.Packet.PacketReader.ReadString(Int32 length) in PATH:line 53
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target,Object[] arguments,Signature sig,Boolean constructor,Boolean wrapExceptions)
--- End of stack trace from prevIoUs location where exception was thrown ---
   ...
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

我读了一些有关错误将如何冒出来的文章,所以我尝试的第一件事是将主语句包装在program.cs中,但这都不起作用。我尝试的下一件事情是在另一个线程上看到的一个解决方案,该线程说要在AppDomain.CurrentDomain中使用委托,所以我这样做了,但也不起作用,程序退出了。这些是代表:

AppDomain.CurrentDomain.FirstChanceException += (sender,eventArgs) => {
    Debug.WriteLine(eventArgs.ToString());
};

AppDomain.CurrentDomain.UnhandledException += (sender,exception) => {
    Debug.WriteLine(exception.ToString());
};

我来自Java,程序在运行时错误后没有退出;我不确定c#为何会出现这种情况,并且不胜感激技巧和建议。谢谢!

编辑:这是一个控制台应用程序

解决方法

没有代码很难有一个主意,但这也许可以为您提供帮助。

捕获未处理的异常的用法是在这些事件上使用处理程序:

AppDomain.CurrentDomain.UnhandledException += OnAppDomainException;

Application.ThreadException += OnThreadException; // WinForms

例如:

static private void OnAppDomainException(object sender,UnhandledExceptionEventArgs args)
{
  if ( args.ExceptionObject == null ) return;
  Handle(sender,(Exception)args.ExceptionObject);
}

static private void OnThreadException(object sender,ThreadExceptionEventArgs args)
{
  if ( args.Exception == null ) return;
  Handle(sender,args.Exception);
}

具有:

static private void Handle(object sender,Exception ex)
{
  try
  {
    Debug.WriteLine(ex.Message);
  }
  catch
  {
  }
  Console.WriteLine(ex.Message);
  // Or MessageBox.Show(ex.Message);
}

您还可以显示一些高级信息,例如堆栈和内部异常链,源代码文件和行号,以及在使用GUI的情况下询问用户如何处理(继续或终止)表单

我从没使用过FirstChanceException,并且文档告诉我们它不是用来管理异常的。

请注意,在控制台应用程序中,执行是从Main方法的开始到结束,并且没有Application事件池管理器和调度程序循环使程序保持运行状态,直到触发该程序为止。退出。

因此,如果发生异常,除非您有一个循环进行重试(例如发生异常)或使程序保持运行的任何内容,否则该过程将退出。

因此对于控制台应用程序,您可以拥有一个带有循环的文本主菜单,直到用户选择退出为止,每个操作都带有一个try catch finally,以确保在发生以下情况时用户返回到菜单:与菜单操作关联的选定方法。

否则,一旦捕获到AppDomain异常,您就可以记录并显示它,但是该过程在任何情况下都将终止,并且您什么也不能做:这很正常,因为现在您不在Main之外方法,这就是结束。

基本上,您可以执行以下操作:

static public void Main(string[] args)
{
  try
  {
    Test();
  }
  catch (Exception ex)
  {
    try
    {
      Debug.WriteLine(ex.Message);
    }
    catch
    {
    }
    Console.WriteLine(ex.Message);
    Console.WriteLine("Restart?");
    if ( Console.ReadLine() == "yes" )
      Main(args);
  }
}

static void Test()
{
  throw new Exception("test error");
}

使用调试堆栈中的高级信息,您可以:

test error

Type: System.Exception
Module: ConsoleApp.exe
Thread: Main
File: Program.cs
Method: ConsoleApp.Program.Test
Line: 73

Restart?
no

How to get line number(s) in the StackTrace of an exception thrown in .NET to show up

Tracing the Stack