C#中的异常处理

在Program.cs中添加如下代码,之后整个应用程序都不需要额外处理异常了。所以的异常都会在这里处理

补充:

        还需要考虑没有文件的写权限,catch (UnauthorizedAccessException ex)

       Access to the path 'D:ChuckLuGitEdenredLISA_5.0.0.0LISA.ControlPanelLISA.ControlPanelinDebuglog20171206.0.log' is denied.

        还需要考虑文件被其他进程占用 ,catch (IOException ex)

       The process cannot access the file 'D:ChuckLuGitEdenredLISA_5.0.0.0LISA.ControlPanelLISA.ControlPanelinDebuglog20171206.0.log' because it is being used by another process.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using WinClient.UI;
using ZBM.ZITaker.Log;
using ZBM.Utility;

namespace WinClient
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                Application.ThreadException += Application_ThreadException;//处理UI线程的异常

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new FormMain());
            }
            catch (Exception ex)
            {
                DealException(ex);
            }
        }

        /// <summary>
        /// 处理UI线程的异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            DealException(e.Exception);
        }

        static void DealException(Exception ex)
        {
            if (ex != null)
            {
                ExceptionLog.Instance.WriteLog(ex, LogType.UI);
                ZBMMessageBox.ShowError(ex);
            }
        }
    }
}

解释:
Application.ThreadException处理的是UI线程的异常

需要注意的是  还有另外一个处理异常的事件(然并卵)

AppDomain.CurrentDomain.UnhandledException处理的是非UI线程的异常(如:子线程的异常)

需要注意的是AppDomain.CurrentDomain.UnhandledException虽然能够捕获子线程的异常,但是子线程那边还是会崩溃的。从未导致整个应用程序结束。

这就要求,子线程需要自行捕获异常,然后将异常抛出到UI线程

this.BeginInvoke((Action)delegate
{
throw ex;
});

通过以下方式,将非UI线程的线程抛出到UI线程来处理。

private void CreateThread()
        {
            Thread thread = new Thread(Temp);
            thread.IsBackground = true;
            thread.Start();
        }

        private void Temp()
        {
            try
            {
                int a = 3;
                int b = 0;
                int c = a / b;
            }
            catch (Exception ex)
            {
                this.BeginInvoke((Action)delegate
                {
                    throw ex;
                });
            }
          
        }

以上处理方法的不足之处在于,所以的异常都会以MessageBox的方式显示给用户

但是,如果有的线程是需要一直在后台运行的,那么多捕获到异常后。显示MessageBox的时候,貌似会把UI卡死。

===============2015年09月07日更新====================

子线程的线程还是需要通过事件通知的方式来处理,因为并不是所有的类都有BeginInvoke的方法

class ChildThreadExceptionOccuredEventArgs : EventArgs
{
internal Exception Exception;
}

class EventNotifyManager
    {

        private EventNotifyManager() { }
        private static readonly EventNotifyManager instance = new EventNotifyManager();

        public static EventNotifyManager Instance
        {
            get { return instance; }
        }

        /// <summary>
        /// 子线程出现异常 子线程的异常无法抛出到主线程,所以需要使用事件通知机制
        /// </summary>
        public event EventHandler<ChildThreadExceptionOccuredEventArgs> ChildThreadExceptionOccured;
        public void OnChildThreadExceptionOccured(ChildThreadExceptionOccuredEventArgs e)
        {
            EventHandler<ChildThreadExceptionOccuredEventArgs> handler = ChildThreadExceptionOccured;
            if (handler != null)
            {
                handler(this, e);
            }
        }

    }

可以在Main函数中,增加注册此事件,然后在启用子线程的时候,在子线程的处理方法中,try catch,捕获到异常之后,就用这个事件把异常抛出到主线程中

原文地址:https://www.cnblogs.com/chucklu/p/4704775.html