首页 > 代码库 > 各类异常捕获

各类异常捕获

一、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入口函数中:

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异常)。

二、Task异常捕获:

1)使用Wait捕获(因为Wait会把Task异常放入到主线程,所以主线程可以捕获)。

注意,使用Wait捕获的异常不是Exception而是AggregateException,其中可以获得InnerExceptions,使用foreach的Exception遍历:

 try            {                Task.Factory.StartNew(() =>                   {                       throw new Exception("人工创建的线程异常");                   }).Wait();            }            catch (AggregateException ex)            {                foreach (var item in ex.Flatten().InnerExceptions)                {                    //在这里处理你的异常                }            }

2)在Task内部处理(推荐)

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

3)使用Continue方法处理:

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

4)当使用await(异步的时候),直接在GUI线程try……catch……捕获异常(像普通代码一样,什么异常就catch什么异常)。

5)所有Task的异常(没有使用await或者Wait,纯多线程异常,内部也没有处理过)无法被主线程捕获,此时应该在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("人工创建的线程异常");            });            GC.Collect();            GC.WaitForPendingFinalizers();        }    }}

注意:因为UnobservedTaskException必须在垃圾回收到Finalize之后才会显示,所以不一定每次都被捕获。为提高精度,必须使用GC方法。

各类异常捕获