zoukankan      html  css  js  c++  java
  • 【转】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);
    }
  • 相关阅读:
    leetcode 576. Out of Boundary Paths 、688. Knight Probability in Chessboard
    leetcode 129. Sum Root to Leaf Numbers
    leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings
    leetcode 402. Remove K Digits 、321. Create Maximum Number
    leetcode 139. Word Break 、140. Word Break II
    leetcode 329. Longest Increasing Path in a Matrix
    leetcode 334. Increasing Triplet Subsequence
    leetcode 403. Frog Jump
    android中webView加载H5,JS不能调用问题的解决
    通过nginx中转获取不到IP的问题解决
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/6281919.html
Copyright © 2011-2022 走看看