在WinRT中,我们可以通过Application.UnhandledException来记录未处理异常,从而方便错误定位和修正。
UnhandledException += (s, e) =>
{
//e.Handled = true;
LogError(e.Message);
};
但是,Application.UnhandledException有一个bug:UnhandledException不能捕获异步函数的异常。
例如,对于如下两个函数,UnhandledException能捕获Button_Click_1抛出的异常,但却不能捕获Button_Click_2抛出的异常。Button_Click_2函数执行接直接导致程序crash。
public class MainPage : Page
{
private void Button_Click_1(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
}
注:由于的async void函数是在synchronization context中执行,并不是在Task中执行,因此,也不能通过TaskScheduler.UnobservedTaskException来捕获改异常。
由于WinRT程序Crash的时候是直接闪退的,不像桌面程序那样能跳个对话框出来让我们挂上调试器看调用栈。对于这种异常,我们唯一能看到的信息是错误日志下的一条未处理异常的日志:
- <EventData>
<Data>应用程序: App1.exe Framework 版本: v4.0.30319 说明: 由于未经处理的异常,进程终止。异常信息: System.InvalidOperationException 堆栈: 在
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在
System.Threading.WinRTSynchronizationContext+Invoker.<InvokeCore>b__0(System.Object) 在
System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) 在
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 在
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 在
System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在
System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</Data>
</EventData>
非常要命的是这个错误信息里面看不到原始的调用栈,就连异常函数的信息都看不到,只能看到一个异常类型,对错误定位的帮助非常有限,唉,那怕记录个异常函数名也行呀。
在网上搜了一下,MSDN上也有人讨论这个问题No UnhandledException fired from async event callback,但是依然没有解决方案,非常令人头疼。