WPF 程序 处理未捕获异常,和程序莫名终止说拜拜

http://www.cnblogs.com/liuyueyu/p/4476151.html

百密一疏的Bug很难避免,没有谁能保证,我的程序永远 0 BUG;

 

突然接手一个很庞大的项目,在项目运行期间会莫名异常结束,异常极难重现,还找不出BUG代码,代码太多了。

这个时候就需要把程序中发生的BUG记录下来,知道哪里BUG了,才好下次更新解决。

把所有代码全部加 try catch ?  那就怀孕了,真的搞大了。

 

未捕获的异常处理:

一:C# 在 Application 类中提供了 DispatcherUnhandledException 事件,用于处理UI线程上未捕获的异常

复制代码
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        DispatcherUnhandledException += App_DispatcherUnhandledException;
        base.OnStartup(e);
    }

    void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {
        //e.Exception   发生的异常
        //e.Handled     是否已处理异常事件
    }
}
复制代码

但是 DispatcherUnhandledException 捕获不了 非UI线程上发生的异常

 

二:C# 在 AppDomain 类中提供了 UnhandledException 事件,用于捕获应用程序域中发生的异常

复制代码
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    MessageBox.Show("Unhandle");
//MessageBox.Show((e.ExceptionObject == null ? "Null" : e.ExceptionObject.GetType().Name),
    //    "CurrentDomain_UnhandledException:");
}
复制代码

这样就能捕获应用程序域中发生的异常,当然,包括UI线程和非UI线程异常,如果你有创建应用程序域的需求,创建完成,再绑定下事件即可。

但是AppDomain.UnhandledException 事件没有提供 终止异常,也就是说,异常发生了,你没捕获,这里通知一下,但是该程序结束还得结束。

 

在这里要特别提到官方封装的 Delegate.BeginInvoke();

"已知:"在异步函数中发生了异常并且没处理:

"求解:"

1.没调用 Delegate.EndInvoke() 函数:

    终止执行。 程序不会挂掉,异常丢弃。这是种很隐蔽的BUG,很难发现。

    AppDomain.UnhandledException 事件不会通知发生了异常,这里要特别注意。

复制代码
public void Hello()
{
    World();
    Load();
}

public void World()
{
throw new Exception();
} public void Load() { MessageBox.Show("Suc"); } var action = new Action(Hello); action.BeginInvoke(null, null);
复制代码

像这种示例,如果在World() 方法中发生了异常,线程会立即终止,Load() 函数就不会执行,程序也不会终止。

一个函数没有执行,也许就会导致很严重的异常,还很难发现。

 

2.调用了 Delegate.EndInvoke() 函数:

    异常抛出, 程序挂掉。

    AppDomain.UnhandledException 事件会通知发生了异常

 

这里也许会有个需求,如果我想处理 AppDomain.UnhandledException 事件中的异常怎么办?程序挂了太恶心了。

我们来继续扩展这个框架

解决在非UI线程中访问UI 异常的小方法

复制代码
/// <summary>
/// 委托 扩展类
/// </summary>
public static class DelegateExtension
{
/// <summary> /// 可以被捕获异常的异步调用 /// </summary> /// <param name="dele"></param> public static void UnsafeBeginInvoke(this Delegate dele) { var action = new Action(() => { dele.DynamicInvoke(); }); action.BeginInvoke(new AsyncCallback((ar) => { try { action.EndInvoke(ar); } catch (Exception ex) { App.Current.Dispatcher.BeginInvoke(new Action(() => { throw ex; })); } }), null); } }
复制代码

有点不伦不类哈,厄。把异常推送到UI线程上抛出,让Application.DispatcherUnhandledException 事件处理

 

其它:C# 在 TaskScheduler 类中提供了 UnobservedTaskException 事件,用于捕获 Task 异步异常

 

求评论,求吐槽,求求你^v^ 

posted on 2015-05-04 15:05  ExplorerMan  阅读(865)  评论(0编辑  收藏  举报

导航