• 关于未捕获异常的处理(WPF)


    关于未捕获异常的处理(WPF)

    这一篇文章来谈谈对于WPF应用程序开发中的未捕获异常的处理。

    首先,我们当然是要求应用程序开发人员,尽可能地在程序可能出现异常的地方都去捕捉异常,使用try…catch的方式。但是总是有一些意外的情况可能会发生,这就导致会出现所谓的“未捕获异常(UnhandledException)”。对于这一类异常,如果我们没有一个合适的策略进行处理,则当其发生的时候,会给用户带来不太好的使用体验。例如下面这样

    image

    备注:这个截图是在Windows 8上面做的,其他操作系统看到的界面可能略有不同。

    用户看到这个窗口的时候,其实一般只能点击Close the prograrm按钮。也就是说,这种情况下会导致用户无法继续使用这个程序,而且他们还得不到任何具体的消息:到底发生了什么事情了?除非他们去查看Windows的事件日志。(但一般的用户是不太会这个操作的)

    image

    我们可以看到在Windows事件日志中,会有两个具体的事件。首先是一个.NET Runtime的事件

    image

    然后是一个Application Error的事件

    image

    通常来说,这样的用户体验有值得改进的地方。我们虽然不能防止异常的产生,但是当意外发生的时候,我们应该要以更好地方式地通知到用户,或者尽可能地不要影响用户当前的操作。

    在WPF这种应用程序中,会有两大类未处理异常:一类是在UI线程抛出来的,例如点击了用户界面上面的某个控件,然后执行某个代码的时候,遇到了异常;另一类是非UI线程跑出来的,例如在一个多线程的程序里面,工作线程的代码遇到了异常。

    对于UI线程的未处理异常,我们可以通过监控下面这个事件来处理

    Application.Current.DispatcherUnhandledException   http://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx

    一个参考代码如下:

    using System;
    using System.Windows;
    
    namespace WpfApplicationExceptionSample
    {
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            public App()
            {
                Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
            }
    
    
            void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
            {
                MessageBox.Show("我们很抱歉,当前应用程序遇到一些问题,该操作已经终止,请进行重试,如果问题继续存在,请联系管理员.", "意外的操作", MessageBoxButton.OK, MessageBoxImage.Information);//这里通常需要给用户一些较为友好的提示,并且后续可能的操作
    
                e.Handled = true;//使用这一行代码告诉运行时,该异常被处理了,不再作为UnhandledException抛出了。
            }
        }
    }
    

    运行的效果大致如下

    image

    对于非UI线程抛出的未处理异常,我们需要监控另外一个事件来处理

    AppDomain.CurrentDomain.UnhandledException  http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx 

    一个参考代码如下

    using System;
    using System.Windows;
    
    namespace WpfApplicationExceptionSample
    {
        /// <summary>
        /// Interaction logic for App.xaml
        /// </summary>
        public partial class App : Application
        {
            public App()
            {
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            }
    
            void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
            {
                MessageBox.Show("我们很抱歉,当前应用程序遇到一些问题,该操作已经终止,请进行重试,如果问题继续存在,请联系管理员.", "意外的操作", MessageBoxButton.OK, MessageBoxImage.Information);
            }
    
    
        }
    }
    

    令人不解的是,这个事件中没有和前面那个事件一样的e.Handled参数,就是说,虽然这样是可以捕捉到非UI线程的异常,而且也可以进行相应的处理,但是应用程序还是会退出,也就是说这个异常还是被当作是未处理异常继续汇报给Runtime。

    为了改进这一点,我们可以通过修改配置文件来实现。

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <legacyUnhandledExceptionPolicy enabled="1"/>
      </runtime>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
    </configuration>

    这里的legacyUnhandledExceptionPolicy,如果enabled=1的话,用意是使用早期版本的异常处理策略。

    从ASP.NET传递参数给水晶报表

    上次Insus.NET有简单写了一篇文章《Visual Studio 2012使用水晶报表Crystal Report》 http://www.cnblogs.com/insus/archive/2013/05/22/3090786.html
    此篇只是简单介绍了Visual Studio 2012可以方便是以快捷安装Crystal Report了,Crystal Report的创建与显示于ASP.NET网页上。

    今天Insus.NET 想跟大家分享的是从ASP.NET网页传递参数给水晶报表。

    首先创建两个存储过程,第一个是参数,Insus.NET将把这个参数做成一个下拉式菜单(DropDownList),供用户选择。


    第二个存储过程,是供水晶报使用:


    然后去asp.net程序,创建两个对象(class类):



    准备另外一个类:



    准备完毕,我们开始创建一个水晶报表。创建过程中,为了减少篇幅而且生动形象,Insus.NET把过程做成一个实时操作。让你慢慢看来。



    我们在网站上创建一个网页asp.net,用来显示报表。不过我们的重点是从asp.net传递参数给水晶报表。因此先在网页放一个DropDownList,并绑定数据给它。



    去.aspx.cs为DropDownList写绑定程序:



    上图中#13和#23行代码,可以参考:http://www.cnblogs.com/insus/archive/2013/01/28/2880618.html


    现在我们开始在网页上显示水晶报了,添加一个铵钮(#15行html markup)。把光标定在#16行位置,去工具栏,双击



    将产生下图#3行和#16行html markup。




    接下来,我们去写铵钮的事件:



    引用命名空间:

    using Insus.NET;
    using CrystalDecisions.CrystalReports.Engine;
    using CrystalDecisions.Shared;


    第#34至#39行为本篇博文重点,参数设置:

     ParameterValues prmV;
     ParameterDiscreteValue pdv = new ParameterDiscreteValue();
     prmV = rptDoc.DataDefinition.ParameterFields["@FruitKind_nbr"].CurrentValues;
     pdv.Value = this.DropDownList1.SelectedItem.Value;
     prmV.Add(pdv);
     rptDoc.DataDefinition.ParameterFields["@FruitKind_nbr"].ApplyCurrentValues(prmV);

    最后是网页实时操作,在浏览时,遇上一些小问题,及解决方法,还是显示的一些格式情况,均一一展现。



     
     
  • 相关阅读:
    [悟]你为什么想创业
    [悟] 因上努力,果上随缘
    自己写个多任务多线程断点下载框架
    大道甚夷,而人好径
    [经验帖]外包如何定价
    python 基础语法
    python 中文编码问题
    python的运行机制和版本区别
    [转]linux 调用动态库so文件
    shell join详解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3281620.html
Copyright © 2020-2023  润新知