【转】UWP 捕获全局异常

2017-01-13 11:35:04来源:cnblogs.com作者:眾尋人点击

转自:http://www.cnblogs.com/youngytj/p/4749004.html

异步(async)方法中的异常无法被App的UnhandledException捕获的问题

这是一个比较严重的问题.目前已知很多的做法就是局部try catch来解决这个问题.这样做是很容易导致Process被强制终止然后引起闪退的问题的.

我这里用了一个线程同步模型类解决这个问题.

using System;using System.Threading;using Windows.UI.Xaml.Controls;namespace AiJianShu.ExceptionHandler{    internal class ExceptionHandlingSynchronizationContext : SynchronizationContext    {        /// <summary>        /// 注册事件.  需要在OnLaunched和OnActivated事件中调用        /// </summary>        /// <returns></returns>        public static ExceptionHandlingSynchronizationContext Register()        {            var syncContext = Current;            if (syncContext == null)                throw new InvalidOperationException("Ensure a synchronization context exists before calling this method.");            var customSynchronizationContext = syncContext as ExceptionHandlingSynchronizationContext;            if (customSynchronizationContext == null)            {                customSynchronizationContext = new ExceptionHandlingSynchronizationContext(syncContext);                SetSynchronizationContext(customSynchronizationContext);            }            return customSynchronizationContext;        }        /// <summary>        /// 将线程的上下文绑定到特定的Frame上面        /// </summary>        /// <param name="rootFrame"></param>        /// <returns></returns>        public static ExceptionHandlingSynchronizationContext RegisterForFrame(Frame rootFrame)        {            if (rootFrame == null)                throw new ArgumentNullException("rootFrame");            var synchronizationContext = Register();            rootFrame.Navigating += (sender, args) => EnsureContext(synchronizationContext);            rootFrame.Loaded += (sender, args) => EnsureContext(synchronizationContext);            return synchronizationContext;        }        private static void EnsureContext(SynchronizationContext context)        {            if (Current != context)                SetSynchronizationContext(context);        }        private readonly SynchronizationContext _syncContext;        public ExceptionHandlingSynchronizationContext(SynchronizationContext syncContext)        {            _syncContext = syncContext;        }        public override SynchronizationContext CreateCopy()        {            return new ExceptionHandlingSynchronizationContext(_syncContext.CreateCopy());        }        public override void OperationCompleted()        {            _syncContext.OperationCompleted();        }        public override void OperationStarted()        {            _syncContext.OperationStarted();        }        public override void Post(SendOrPostCallback d, object state)        {            _syncContext.Post(WrapCallback(d), state);        }        public override void Send(SendOrPostCallback d, object state)        {            _syncContext.Send(d, state);        }        private SendOrPostCallback WrapCallback(SendOrPostCallback sendOrPostCallback)        {            return state =>            {                try                {                    sendOrPostCallback(state);                }                catch (Exception ex)                {                    if (!HandleException(ex))                        throw;                }            };        }        private bool HandleException(Exception exception)        {            if (UnhandledException == null)                return false;            var exWrapper = new AysncUnhandledExceptionEventArgs            {                Exception = exception            };            UnhandledException(this, exWrapper);#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION            if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();#endif            return exWrapper.Handled;        }        public event EventHandler<AysncUnhandledExceptionEventArgs> UnhandledException;    }    public class AysncUnhandledExceptionEventArgs : EventArgs    {        public bool Handled { get; set; }        public Exception Exception { get; set; }    }}

使用实例:

public App(){    this.InitializeComponent();    this.Suspending += OnSuspending;    this.UnhandledException += App_UnhandledException;}private void RegisterExceptionHandlingSynchronizationContext(){    ExceptionHandlingSynchronizationContext        .Register()        .UnhandledException += SynchronizationContext_UnhandledException;}private async void App_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e){    e.Handled = true;    await new MessageDialog("Application Unhandled Exception:/r/n" + e.Exception.Message)        .ShowAsync();}private async void SynchronizationContext_UnhandledException(object sender, AysncUnhandledExceptionEventArgs e){    e.Handled = true;    await new MessageDialog("Synchronization Context Unhandled Exception:/r/n" + e.Exception.Message)        .ShowAsync();}protected override void OnLaunched(LaunchActivatedEventArgs e){    RegisterExceptionHandlingSynchronizationContext();#if DEBUG    if (System.Diagnostics.Debugger.IsAttached)    {        this.DebugSettings.EnableFrameRateCounter = true;    }#endif    Frame rootFrame = Window.Current.Content as Frame;    // 不要在窗口已包含内容时重复应用程序初始化,    // 只需确保窗口处于活动状态    if (rootFrame == null)    {        // 创建要充当导航上下文的框架,并导航到第一页        rootFrame = new Frame();        rootFrame.NavigationFailed += OnNavigationFailed;        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)        {            //TODO: 从之前挂起的应用程序加载状态        }        // 将框架放在当前窗口中        Window.Current.Content = rootFrame;    }    if (rootFrame.Content == null)    {        // 当导航堆栈尚未还原时,导航到第一页,        // 并通过将所需信息作为导航参数传入来配置        // 参数        rootFrame.Navigate(typeof(MainPage), e.Arguments);    }    // 确保当前窗口处于活动状态    Window.Current.Activate();}protected override void OnActivated(IActivatedEventArgs args){    RegisterExceptionHandlingSynchronizationContext();    base.OnActivated(args);}

 

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台