问题描述
我创建了一个在客户端之间发送数据的程序,一旦发生运行时异常,整个程序就会退出。
我想为所有运行时异常创建一个全局捕获器,这样我的程序就不会在发生运行时异常时退出。发生异常时,程序退出并显示以下消息:
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