各種異常捕獲

1、UI線程異常:多線程

1)直接在主線程中的異常,直接用try……catch捕獲(若是你懷疑某個代碼會拋出異常)。異步

2)其它可能性:建議使用Application.ThreadException+Application.SetUnhandledException捕獲異常,並防止應用程序終止。函數

1  private void button1_Click(object sender, EventArgs e)
2         {
3             throw new Exception("UI異常拋出");
4         }

在Program.cs入口函數中:spa

public class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException += Application_ThreadException;
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 f1 = new Form1();
            Application.Run(f1);
        }

        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            using (var f = File.AppendText("c:\\error2.txt"))
            {
                f.WriteLine(e.Exception.Message);
            }
        }
    }

點擊按鈕,會拋出異常(UI異常)。被寫入日誌,程序能夠繼續運行。線程

2、Task異常捕獲:日誌

1)使用Wait捕獲(由於Wait會把Task異常放入到主線程,因此主線程能夠捕獲)。code

注意,使用Wait捕獲的異常不是Exception而是AggregateException,其中能夠得到InnerExceptions,使用foreach的Exception遍歷:orm

 try
            {
                Task.Factory.StartNew(() =>
                   {
                       throw new Exception("人工建立的線程異常");
                   }).Wait();

            }
            catch (AggregateException ex)
            {
                foreach (var item in ex.Flatten().InnerExceptions)
                {
                    //在這裏處理你的異常
                }
            }

2)在Task內部處理(推薦)blog

 Task.Factory.StartNew(() =>
                   {
                      try
                        {
                        }
                      catch (Exception e)
                         {
                         }
                   }).Wait();

3)使用Continue方法處理:it

 Task.Factory.StartNew(() =>
            {
                throw new Exception("人工建立的線程異常");
            }).ContinueWith(t => t.Exception.Flatten()……);

4)當使用await(異步的時候),直接在GUI線程try……catch……捕獲異常(像普通代碼同樣,什麼異常就catch什麼異常)。

5)全部Task的異常(沒有使用await或者Wait,純多線程異常,內部也沒有處理過)會在Task被Finailize以後被主線程捕獲,拋出異常並終止主程序。此時應該在WinForm(Console控制檯在Main入口函數中),使用TaskSchedule.UnobservedTaskException:

namespace CSharpWinForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        }


        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            using (var f = File.AppendText("c:\\error.txt"))
            {
                foreach (var item in e.Exception.Flatten().InnerExceptions)
                {
                    f.WriteLine("Task異常:"+item.Message);
                }
            }
            e.SetObserved();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                throw new Exception("人工建立的線程異常");
            });
            Thread.Sleep(500);
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }
}

3)Thread和ThreadPool的異常:

此異常會致使主程序崩潰,必須使用內部try……catch捕獲。固然,咱們能夠使用AppDomain.CurrentDomain的UnhandledException捕獲(可是沒法取消異常,仍然會有此異常):

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(() => 
            {
                throw new Exception("異常");
            });
            th.Start();
        }
    }
 public class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 f1 = new Form1();
            Application.Run(f1);
        }


        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            using (var f = File.AppendText("c:\\error2.txt"))
            {
                f.WriteLine(e.ExceptionObject.ToString());
            }
        }
    }
相關文章
相關標籤/搜索