zoukankan      html  css  js  c++  java
  • 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^ 

  • 相关阅读:
    数据结构-连续子数组的最大和
    数据结构-并查集
    nginx开启代理后,出现net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)错误
    计算出n阶乘中尾部零的个数
    常见的加密方式总结
    idea中lombok不生效
    纯真ip地址数据库使用
    go mod使用
    exec: "gcc": executable file not found in %PATH%解决办法
    java多线程系列1-初识多线程多线程4种实现方式
  • 原文地址:https://www.cnblogs.com/ExMan/p/4476232.html
Copyright © 2011-2022 走看看