五、 处理异步操作中的异常
本示例学习如何在异步函数中处理异常,学习如何对多个并行的异步操作使用await时聚合异常。
1.程序示例代码如下。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ThreadAsyncDemo { class Program { static void Main(string[] args) { Console.WriteLine(string.Format("----- 处理异步操作中的异常----")); Task t = AsyncProcess(); t.Wait(); Console.Read(); } async static Task AsyncProcess() { Console.WriteLine(string.Format("----- 1 单个异常处理----")); try { string result =await GetInfoAsync("Task 1", 2); Console.WriteLine(result); } catch (Exception ex) { Console.WriteLine(string.Format("异常信息:{0}",ex.Message)); } Console.WriteLine(string.Format(" ------- ----")); Console.WriteLine(string.Format("----- 2 多个异常处理----")); Task<string> task1 = GetInfoAsync("Task 1", 3); Task<string> task2 = GetInfoAsync("Task 2",2); try { string[] results = await Task.WhenAll(task1, task2); Console.WriteLine((string.Format("结果数量:{0}",results.Length))); foreach (var item in results) { Console.WriteLine(item); } } catch (Exception ex) { Console.WriteLine(string.Format("异常信息:{0}", ex.Message)); } Console.WriteLine(string.Format(" ------- ----")); Console.WriteLine(string.Format("----- 3 多个异常处理 在AggregateException----")); Task<string> task3 = GetInfoAsync("Task 3", 3); Task<string> task4 = GetInfoAsync("Task 4", 2); Task<string[]> task5 = Task.WhenAll(task3, task4); try { string[] results5 = await task5; Console.WriteLine((string.Format("结果数量:{0}", results5.Length))); foreach (var item in results5) { Console.WriteLine(item); } } catch { var aex = task5.Exception.Flatten(); //获取AggregateException var exs = aex.InnerExceptions; Console.WriteLine(string.Format("异常信息:{0}", exs.Count)); int i = 0; foreach (var item in exs) { i++; Console.WriteLine(string.Format(" ----- {0} ----",i)); Console.WriteLine(string.Format("异常信息:{0}", item.Message)); } } } async static Task<string> GetInfoAsync(string name,int second) { Console.WriteLine(string.Format(" Task {0} 正在运行在线程 ID={1}上。这个工作线程是否是线程池中的线程:{2}", name,
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread)); await Task.Delay(TimeSpan.FromSeconds(second)); throw new Exception(string.Format("{0} 抛出异常信息!", name)); } } }
2.程序运行结果,如下图。
这个程序一共有三个场景来学习使用async与await时,关于异常处理的常见情况。
第一种情况最简单,与常见的同步 代码几乎一样,我们只使用try catch即可获取异常信息。
第二种情况是对一个以上的异步异常使用await时,则只能从aggregateexception对象中得到第一个异常。
第三种情况中,我们使用aggregateException中的flatten方法将层级异常放入一个列表,并从中提取所有的底层异常。
六、 避免使用捕获的同步上下文
本示例学习使用await来获取异步操作结果时,同步上下文行为的结节,并如