• 【转】UWP 捕获全局异常


    转自: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:
    " + e.Exception.Message)
            .ShowAsync();
    }
    
    private async void SynchronizationContext_UnhandledException(object sender, AysncUnhandledExceptionEventArgs e)
    {
        e.Handled = true;
    
        await new MessageDialog("Synchronization Context Unhandled Exception:
    " + 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);
    }
  • 相关阅读:
    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten
    修改git地址
    Clipboard使用
    Electron as GUI of Python
    VUE AXIOS封装三
    Vue-Cli3/Webpack / i18n / image / CDN vue项目优化总结
    echarts 折线图点击高亮
    vue中 左侧导航条 多个toggleClass
    js中异常处理
    Element UI disableddate设置动态时间,结束日期不可大于开始日期以及时间点
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/6281919.html
Copyright © 2020-2023  润新知