随笔 - 743  文章 - 8 评论 - 896 trackbacks - 19

在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,但是依然没有解决方案,非常令人头疼。

 

posted on 2012-11-23 15:03 天方 阅读(...) 评论(...) 编辑 收藏