[C#6] 8-异常增强

简介: 0. 目录 C#6 新增特性目录 1. 在catch和finally块中使用await 在C#5中引入一对关键字await/async,用来支持新的异步编程模型,使的C#的异步编程模型进一步的简化(APM->EAP->TAP->await/async,关于C#中的异步编程模型的不是本篇文章的介绍重点,详细的资料请移步这里Asynchronous Programming Pattern)。

0. 目录

C#6 新增特性目录

1. 在catch和finally块中使用await

在C#5中引入一对关键字await/async,用来支持新的异步编程模型,使的C#的异步编程模型进一步的简化(APM->EAP->TAP->await/async,关于C#中的异步编程模型的不是本篇文章的介绍重点,详细的资料请移步这里Asynchronous Programming Pattern)。在C#5中虽然引入了await/async,但是却有一些限制,比如不能再catch和finally语句块中使用,C#6中将不再受此限制。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 namespace csharp6
 6 {
 7     internal class Program
 8     {
 9         private static void Main(string[] args)
10         {
11             do
12             {
13                 Log(ConsoleColor.White, "caller method begin", true);
14                 CallerMethod();
15                 Log(ConsoleColor.White, "caller method end");
16             } while (Console.ReadKey().Key != ConsoleKey.Q);
17         }
18 
19         public static async void CallerMethod()
20         {
21             try
22             {
23                 Log(ConsoleColor.Yellow, "try ", true);
24                 throw new Exception();
25             }
26             catch (Exception)
27             {
28                 Log(ConsoleColor.Red, "catch await begin", true);
29                 await AsyncMethod();
30                 Log(ConsoleColor.Red, "catch await end");
31             }
32             finally
33             {
34                 Log(ConsoleColor.Blue, "finally await begin", true);
35                 await AsyncMethod();
36                 Log(ConsoleColor.Blue, "finally await end");
37             }
38         }
39 
40         private static Task AsyncMethod()
41         {
42             return Task.Factory.StartNew(() =>
43             {
44                 Log(ConsoleColor.Green, "async method begin");
45                 Thread.Sleep(1000);
46                 Log(ConsoleColor.Green, "async method end");
47             });
48         }
49 
50         private static void Log(ConsoleColor color, string message, bool newLine = false)
51         {
52             if (newLine)
53             {
54                 Console.WriteLine();
55             }
56             Console.ForegroundColor = color;
57             Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");
58         }
59     }
60 }

运行结果如下:

如果你细心的话会发现async method begin:6这一行的颜色居然不是我设置的绿色,而是白色,而且顺序也出现了错乱;而你再运行一次,它可能就是绿色了。这其实是由于我在Log方法(非线程安全的方法)里面的两行代码被多个线程争抢调用引起的:

1 Console.ForegroundColor = color;
2 Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");

我们可以做点小改动来让Log方法做到线程安全(在C#中有很多方式可以做到,这只是其中一种):

 1 [MethodImpl(MethodImplOptions.Synchronized)]
 2 private static void Log(ConsoleColor color, string message, bool newLine = false)
 3 {
 4     if (newLine)
 5     {
 6         Console.WriteLine();
 7     }
 8     Console.ForegroundColor = color;
 9     Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");
10 }

貌似有点跑题了,回归正题,在catch和finally语句块中支持await关键字并不需要IL指令的支持,也不需要CLR的支持,而仅仅是编译器做出的代码转换(await/async就像lambda一样到delegate一样)。具体的IL就不做展开了,太庞大了,贴个图看下大致的情况:

我们在CallerMethod中所写的代码,被转移到MoveNext中(更详细的资料请移步园友"Dev_Eric"的一篇博客:进阶篇:以IL为剑,直指async/await)(包括catch和finally中的await语句)。

2. 异常过滤器

其实这个语言特性在VB,F#里面早就支持了,现在C#6里面也可以使用了。

1 try { … }
2 catch (Exception e) when (filter(e))
3 {
4 5 }

其中when这一块就是异常过滤器生效的地方,when后面跟一个表达式,表达式结果如果为true,则进入当前catch语句块。

3. 参考

Asynchronous Programming Patterns

C# 6.0 await in catch/finally

C# 6.0 Exception filters

http://www.sadev.co.za/content/exception-filtering-c-6

作者: Blackheart
目录
相关文章
|
1月前
|
Java 应用服务中间件
性能场景之异常场景设计及分析
【2月更文挑战第20天】性能场景之异常场景设计及分析
29 1
性能场景之异常场景设计及分析
|
4月前
获取包装异常中真实异常
获取包装异常中真实异常
28 0
|
5月前
|
机器学习/深度学习 算法框架/工具 Python
pyton数据增强
pyton数据增强
32 0
|
6月前
|
人工智能 程序员 C#
通过简单原理增强软件可靠性
通过简单原理增强软件可靠性
|
7月前
|
Java 编译器 程序员
异常概述与异常体系结构
异常概述与异常体系结构
26 0
|
8月前
|
C语言 C++
【C++】异常的使用和细节
【C++】异常的使用和细节
42 0
|
10月前
|
机器学习/深度学习 人工智能 算法
数据增强方法汇总
数据增强方法汇总
158 0
GoogleGuava - 第 1 章 基本工具——Throwables:简化异常和错误的传播与检查
GoogleGuava - 第 1 章 基本工具——Throwables:简化异常和错误的传播与检查
133 0
GoogleGuava - 第 1 章 基本工具——Throwables:简化异常和错误的传播与检查
|
缓存 Oracle IDE
深入分析Java反射(八)-优化反射调用性能
Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行Debug。
292 0
|
机器学习/深度学习 编解码 数据挖掘
MMClassificiation|实现数据增强的 N 种方法
众所周知,即使是目前最先进的神经网络模型,其本质上也是在利用一系列线性和非线性的函数去拟合目标输出。 既然是拟合,当然越多的样本就能获得越准确的结果,这也是为什么现在训练神经网络所使用的数据规模越来越大的原因。
584 0
MMClassificiation|实现数据增强的 N 种方法