如何捕获和处理 Task.Factory 内部发生的未处理异常
How to capture and handle unhandled exceptions that happens inside Task.Factory
我已经在应用程序启动中编写了这个代码
里面App.xaml.cs
public App()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
DispatcherUnhandledException += App_DispatcherUnhandledException;
Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(Application_DispatcherUnhandledException);
TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(Application_DispatcherUnhandledException2);
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void writeMessage(Exception e)
{
string srMsg = e.InnerException?.Message;
if (srMsg != null)
{
srMsg += "\r\n\r\nStack\r\n" + e.InnerException?.StackTrace;
}
if (srMsg == null)
{
srMsg = e.Message + "\r\n\r\nStack\r\n" + e.StackTrace;
}
srMsg += "\r\n\r\n*********\r\n\r\n";
File.AppendAllText("global_errors.txt", srMsg);
}
private static void Application_DispatcherUnhandledException2(object o, UnobservedTaskExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
writeMessage(e);
}
但是,这仍然不是捕获任务工厂的错误
例如
此线程中的任何提议均无效WPF global exception handler
仅当您通过例如调用 Wait()
或 .Result
或访问其 Exception
属性 观察到 Task
时才会抛出异常。
除非您使用 <ThrowUnobservedTaskExceptions>
配置元素恢复到 .NET Framework 4 中的默认行为并终止进程,否则不会抛出未观察到的异常:
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
如果你真的想捕获异常,你应该在传递给 Task.Factory.StartNew
的委托中进行。您可以按照建议 here.
将此功能包装在扩展方法中
可以通过多种方式获取 StackTrace,具体取决于哪种方式最适合您的需求。无论如何,我建议你尝试以下方法。
- 在项目开始时向
AppDomain.FirstChanceException
事件添加回调,例如在您想要 catch/log 的错误发生之前。这可能类似于以下内容:
public static Main()
{
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
}
private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
}
- 之后,在
CurrentDomain_FirstChanceException
方法中添加Environment.StackTrace
。它将当前 StackTrace
保存为 string
。根据我的测试,它包括 FileName
和 FileLineNumber
.
var currentStackTrace = Environment.StackTrace;
// Now it is on to you on what you want to do with the StackTrace. This could be some kind of logging.
请注意,这将记录 ALL 由 AppDomain
抛出的异常,无论它们是否由代码处理,例如try/catch
。
我已经在应用程序启动中编写了这个代码
里面App.xaml.cs
public App()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
DispatcherUnhandledException += App_DispatcherUnhandledException;
Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(Application_DispatcherUnhandledException);
TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(Application_DispatcherUnhandledException2);
this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void writeMessage(Exception e)
{
string srMsg = e.InnerException?.Message;
if (srMsg != null)
{
srMsg += "\r\n\r\nStack\r\n" + e.InnerException?.StackTrace;
}
if (srMsg == null)
{
srMsg = e.Message + "\r\n\r\nStack\r\n" + e.StackTrace;
}
srMsg += "\r\n\r\n*********\r\n\r\n";
File.AppendAllText("global_errors.txt", srMsg);
}
private static void Application_DispatcherUnhandledException2(object o, UnobservedTaskExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
writeMessage(e.Exception);
}
private static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
writeMessage(e);
}
但是,这仍然不是捕获任务工厂的错误
例如
此线程中的任何提议均无效WPF global exception handler
仅当您通过例如调用 Wait()
或 .Result
或访问其 Exception
属性 观察到 Task
时才会抛出异常。
除非您使用 <ThrowUnobservedTaskExceptions>
配置元素恢复到 .NET Framework 4 中的默认行为并终止进程,否则不会抛出未观察到的异常:
<runtime>
<ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>
如果你真的想捕获异常,你应该在传递给 Task.Factory.StartNew
的委托中进行。您可以按照建议 here.
可以通过多种方式获取 StackTrace,具体取决于哪种方式最适合您的需求。无论如何,我建议你尝试以下方法。
- 在项目开始时向
AppDomain.FirstChanceException
事件添加回调,例如在您想要 catch/log 的错误发生之前。这可能类似于以下内容:
public static Main()
{
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
}
private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
}
- 之后,在
CurrentDomain_FirstChanceException
方法中添加Environment.StackTrace
。它将当前StackTrace
保存为string
。根据我的测试,它包括FileName
和FileLineNumber
.
var currentStackTrace = Environment.StackTrace;
// Now it is on to you on what you want to do with the StackTrace. This could be some kind of logging.
请注意,这将记录 ALL 由 AppDomain
抛出的异常,无论它们是否由代码处理,例如try/catch
。