各类异常捕获

本文详细介绍了在C#中处理UI线程、Task、Thread和ThreadPool异常的方法。包括如何使用try...catch捕获异常、如何利用Application.ThreadException和Application.SetUnhandledException等进行全局异常处理,以及如何在Task和线程中正确处理未捕获的异常。
摘要由CSDN通过智能技术生成

一、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,纯多线程异常,内部也没有处理过)会在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());
            }
        }
    }

 

转载于:https://www.cnblogs.com/ServiceboyNew/p/5873511.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值