本例描述几个常用的异常处理,及可能出现的问题:
finally的相关使用
嵌套异常
捕获多线程的异常[使用事件通知的方式,将异常包装到主线程中]
using System; using System.Threading.Tasks; namespace ConsoleApp_HandleException { class Program { static void Main(string[] args) { //TestInvoke(); //MethodWithTryNesting(); //Console.WriteLine(); //MethodWithTry(); TryCatchMultiThreadException2(); Console.ReadKey(); } #region finally的相关使用 static void TestInvoke() { int result1 = TestIntReturnBelowFinally(); int result2 = TestIntReturnInTry(); User result3 = TestUserReturnInTry(); Console.ReadKey(); } static int TestIntReturnBelowFinally() { int i; try { i = 1; } finally { i = 2; Console.WriteLine("\t 将int结果改为2,finally执行完毕!"); } return i;//执行顺序:try,finally,return i为2,返回2 } static int TestIntReturnInTry() { int i; try { return i = 1;//执行顺序:i=1,finally,return 返回值为1,i=2(在finally中的修改,未能影响到返回值) } finally { i = 2; Console.WriteLine("\t 将int结果改为2,finally执行完毕!"); } } //返回名称为Li si static User TestUserReturnInTry() { User user = new User() { Name = "Zhang san" }; try { return user;//执行顺序:try,finally,return 返回名称为Li si(在finally中的修改,(由于是引用类型,所以)影响到了返回值) } finally { user.Name = "Li si"; Console.WriteLine("\t 将user.Name改为 Li si !"); user = null;//返回值的名称为Li si,因为2个引用指向同一个内存,只是将其中一个引用置空了 } } class User { public string Name; } #endregion #region 捕获异常 /* 避免使用: * catch (Exception err) * { * throw err; * } * * 改用: * catch //(Exception) //可以返回出错的位置 * { * throw; * } * * 外界再次捕获异常时,无法找到原始出错的位置,堆栈被重置了 (只能显示MethodWithTry方法中的catch位置) * */ ////// 嵌套异常 /// static void MethodWithTryNesting() { try { MethodWithTry(); } catch (Exception error1) { Console.WriteLine(error1.StackTrace); } } static void MethodWithTry() { try { Method1(); } //catch (Exception err)//外界再次捕获异常时,无法找到原始出错的位置,堆栈被重置了 (只能显示MethodWithTry方法中的catch位置) //{ // throw err; //} catch //(Exception) //可以返回出错的位置 { throw; } } static int Method1() { int i = 0; return 10 / i; } #endregion #region 捕获多线程的异常[在Windows应用程序中] //public void TryCatchMultiThreadException() //{ // Thread t=new Thread((ThreadStart) delegate // { // try // { // throw new Exception("非UI线程异常"); // } // catch (Exception ex) // { // //将线程内部的异常传递到主线程上 // this.BeginInvoke((Action) delegate // { // throw ex; // }); // } // }); //} #endregion #region 捕获多线程的异常[使用事件通知的方式,将异常包装到主线程中] private static event EventHandlerAggregateExceptionCatched; public class AggregateExceptionArgs : EventArgs { public AggregateException AggregateException { get; set; } } public static void TryCatchMultiThreadException2() { AggregateExceptionCatched += Program_AggregateExceptionCatched; Task t = new Task(() => { try { //do something 执行正常代码,产生了异常 throw new InvalidOperationException("任务并行编码中产生的未知异常"); } catch (Exception err) { AggregateExceptionArgs errArgs = new AggregateExceptionArgs() { AggregateException = new AggregateException(err) }; AggregateExceptionCatched(null, errArgs); } }); t.Start(); Console.WriteLine("主线程即将结束"); Console.ReadKey(); } static void Program_AggregateExceptionCatched(object sender, Program.AggregateExceptionArgs e) { foreach (var item in e.AggregateException.InnerExceptions) { Console.WriteLine("异常类型:{0}{1}来自:{2}{3}异常内容:{4}", item.GetType(), Environment.NewLine, item.Source, Environment.NewLine, item.Message); } } #endregion } }