转自: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);
}

【转】UWP 捕获全局异常的更多相关文章

  1. 在C#代码中应用Log4Net(四)在Winform和Web中捕获全局异常

    毕竟人不是神,谁写的程序都会有bug,有了bug不可怕,可怕的是出错了,你却不知道错误在哪里.所以我们需要将应用程序中抛出的所有异常都记录起来,不然出了错,找问题就能要了你的命.下面我们主要讨论的是如 ...

  2. Android捕获全局异常

    Android捕获全局异常 程序避免不了出现bug,导致程序崩溃,为了尽量不影响用户体验,可以全局捕获异常 效果图 异常捕获处理前 异常捕获处理后(将程序重新启动) 捕获异常的工具类 package ...

  3. SpringBoot捕获全局异常

    1.创建GloableExceptionAop类捕获全局异常 package com.cppdy.exception; import org.springframework.web.bind.anno ...

  4. Android应用捕获全局异常自定义处理

    [2016-06-30]最新的全局异常处理DRCrashHandler已经集成在DR_support_lib库中 具体请看: https://coding.net/u/wrcold520/p/DR_s ...

  5. WebForm 在 Global.asax 中捕获全局异常

    /// <summary> /// 捕获全局异常 /// </summary> /// <param name="sender">sender& ...

  6. C# 捕获全局异常

    一.在Winform程序中捕获全局异常 在winfrom中我们需要了解Application对象中的两个事件 ①Application.ThreadException 事件--当UI线程中某个异常未被 ...

  7. SpringBoot学习笔记(二):SpringBoot访问静态文件、捕获全局异常、集成Thymeleaf、集成JSP

    SpringBoot访问静态文件 什么是静态文件? 不需要通过web容器去得到的文件,直接通过路径就能得到的文件,比如项目的css,js,img等文件. 所有的资源文件都应该在src/main/res ...

  8. C# WinForm捕获全局异常

    网上找的C# WinForm全局异常捕获方法,代码如下: static class Program { /// <summary> /// 应用程序的主入口点. /// </summ ...

  9. express捕获全局异常的三种方法

    场景 express的路由里抛出异常后,全局中间件没办法捕获,需要在所有的路由函数里写try catch,这坑爹的逻辑让人每次都要多写n行代码 官方错误捕获中件间代码如下 app.use(functi ...

随机推荐

  1. 小贴士——提高PHP程序在NGINX代理服务器的性能

    NGINX本身就是面向最大性能的代理服务器,因此在使用NGINX,并没有性能调整的配置工作.但是却有很多选项可用于定制NGINX的行为,利用底层硬件和操作系统. 下面将介绍用于提供PHP在NGINX的 ...

  2. 我的Android 4 学习系列之数据库和Content Provider

    目录 创建数据库和使用SQLite 使用Content Provider.Cusor和Content Value来存储.共享和使用应用程序数据 使用Cursor Loader异步查询Content P ...

  3. jquery表格datagrid单元格显示图片及分页使用

    要想达到自定义显示表格框的目的比如显示图片,超链接,按钮的形式,只需要给列添加formatter属性即可,比如显示图片: columns: [[                             ...

  4. Date与SimpleDateFormat

    Date常用的方法 返回类型 方法名称 备注 Date New Date() 创建当前日期对象 Date New date(long dt) 使用自1970.1.1以后的指定毫秒数创建日期 boole ...

  5. ASP.NET WebApi 增删改查

    本篇是接着上一篇<ASP.NET WebApi 入门>来介绍的. 前言 习惯说 CRUD操作,它的意思是"创建. 读取. 更新和删除"四个基本的数据库操作.许多 HTT ...

  6. printf code

    printf背后的故事 2014-01-14 21:54 by Florian, 41 阅读, 0 评论, 收藏, 编辑 printf背后的故事 说起编程语言,C语言大家再熟悉不过.说起最简单的代码, ...

  7. python 调用shell命令的方法

    在python程序中调用shell命令,是件很酷且常用的事情…… 1. os.system(command) 此函数会启动子进程,在子进程中执行command,并返回command命令执行完毕后的退出 ...

  8. Windows窗口的创建

    Windows窗口创建的基本代码: #include <Windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); i ...

  9. HttpClient的使用-爬虫学习1

    HttpClient的使用-爬虫学习(一) Apache真是伟大,为我们提供了HttpClient.jar,这个HttpClient是客户端的http通信实现库,这个类库的作用是接受和发送http报文 ...

  10. .NET重构—单元测试重构

    .NET重构—单元测试重构 阅读目录: 1.开篇介绍 2.单元测试.测试用例代码重复问题(大量使用重复的Mock对象及测试数据) 2.1.单元测试的继承体系(利用超类来减少Mock对象的使用) 2.1 ...