.Net下的全局异常捕获问题

        全局异常捕获主要目标并不是为了将异常处理掉防止程序崩溃。因为当错误被你的全局异常捕获器抓到的时候,已经证实了你程序中存在BUG。

  一般而言,我们的全局异常捕获主要作用就是接收到异常之后进行异常的反馈。

        大家都知道,异常是通过Throw命令抛出,一路从抛出的模块里上抛,如果中途没有被try...catch...抓住的话就会一直抛到CLR(公共语言运行时)。如果用栈来描述这个过程的话,那就是异常会从栈的栈顶一路下沉,直到中途被try...catch...抓住或者直至沉到栈底,被CLR接住。CLR接收到异常之后的处理方式非常的简单粗暴——直接报错,然后关闭程序。

        只要我们在程序把异常抛给CLR之前,抢先把异常捕获,那就可以做到全局异常处理了。不过这个try...catch...就必须放在栈的最下方。程序运行时栈的最下方函数其实就是程序运行时第一个调用的函数——main()函数。

static void Main()
{
    try
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FrmMain());
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}", ex.GetType(), ex.Message, ex.StackTrace));
    }
}

下面我们运用其他来处理全局异常。

一、Application.ThreadException

假设还是之前的那个程序,我们将程序的Program.cs内容填入以下代码:

static class Program
{
    /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.ThreadException += Application_ThreadException;
         
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FrmMain());
    }
 
    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
        Exception ex = e.Exception;
        MessageBox.Show(string.Format("捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}", ex.GetType(), ex.Message, ex.StackTrace));
    }
}
 

二、子线程异常捕获AppDomain.CurrentDomain.UnhandledException

    /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.ThreadException += Application_ThreadException;
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
         
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FrmMain());
    }
     
    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = e.ExceptionObject as Exception;
        MessageBox.Show(string.Format("捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}\r\nCLR即将退出:{3}", ex.GetType(), ex.Message, ex.StackTrace, e.IsTerminating));
    }

三、WPF的异常捕获

        public App()
        {
            this.Startup += new StartupEventHandler(App_Startup);

            this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);//UI线程的异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);//非UI线程的异常
            System.Threading.Tasks.TaskScheduler.UnobservedTaskException += App_UnobservedTaskException;//异步线程的异常


        }

        void App_Startup(object sender, StartupEventArgs e)
        {
            bool ret;
            mutex = new System.Threading.Mutex(true, "WpfMuerterrrterterttex", out ret);
            if (!ret)
            {
                MessageBox.Show("课堂已经启动!");
                Environment.Exit(0);
            }
        }

        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is System.Exception)
            {
               
            }
        }

        void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
        }

        void App_UnobservedTaskException(object obj, System.Threading.Tasks.UnobservedTaskExceptionEventArgs e)
        {

        }

        int MyExceptionfilter(ref long a)
        {
            MessageBox.Show(a.ToString());
            return 0;
        }

在此处理未处理的异常:

/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

//注册Application_Error
this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);


}


//异常处理逻辑
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//处理完后,我们需要将Handler=true表示已此异常已处理过
MessageBox.Show("程序执行时遇到未处理异常,即将关闭!\n错误信息:"+e.Exception.Message);
Environment.Exit(0);
e.Handled = true;
}
}

 

四、公共语言未能捕获的异常

引入API

        public delegate int CallBack(ref long a);
        CallBack mycall;

        [System.Runtime.InteropServices.DllImport("kernel32")]
        private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int GetWindowText(IntPtr hWnd, ref string strBuffer, int nSize);

WPF的App中

            mycall = new CallBack(MyExceptionfilter);
            SetUnhandledExceptionFilter(mycall);

处理:

        int MyExceptionfilter(ref long a)
        {
            MessageBox.Show(a.ToString());
            return 0;
        }

 

posted @ 2017-11-13 16:20  卖雨伞的小男孩  阅读(892)  评论(0编辑  收藏  举报