详述.NET 4中异常处理的新机制

开发 后端
本文将为大家介绍.NET 4中异常处理的新机制,主要也是针对某些.NET里不能捕捉的一些异常,希望对大家有所帮助。

前几天,有一个朋友问我为什么在.NET里不能捕捉(catch)到一些异常了,而且在调试器里也捕捉不到。研究了一下,是.NET 4.0里新的异常处理机制捣的鬼。

在.NET 4.0之后,CLR将会区别出一些异常(都是SEH异常),将这些异常标识为破坏性异常(Corrupted State Exception)。针对这些异常,CLR的catch块不会捕捉这些异常,即使你用类似下面的代码:

  1. try 
  2.             {  
  3.                 TestMethod();  
  4.             }  
  5.             catch (Exception e)  
  6.             {  
  7.                 Console.WriteLine("Catching exception: {0}", e);  
  8.             } 

也没有办法捕捉到这些异常。之所以要这样设计,在MSDN的文章Handling Corrupted State Exceptions里已经提到了。即,有一些支持插件的程序,例如Visual Studio或者SQL Server,它们支持调用托管代码编写成的插件,但是它们自己本身有很多代码是由非托管的C++写成的。由于插件经常会调用到非托管的API,而很多时间,这些插件的代码根本就不知道如何处理非托管的API抛出来的SEH异常。在4.0以前,因为SEH异常被转换成了跟普通.NET异常相同的异常,这样程序员只要用catch ( Exception e)的模式就可以捕捉到所有的异常。这样处理的问题是,由于SEH异常通常都不是托管代码抛出的,托管代码根本就不知道SHE异常被扔出来的原因,简单的catch ( Exception e)处理使得整个程序会处于一个非常不稳定的状态,使得前面被忽略的问题在后面以更严重的方式出现 — 例如保存被破坏的数据。这样,看起来使用catch ( Exception e)处理所有的异常的方法很简单,但实际上让程序员或者用户在问题延后发生时,分析起来需要花费更多的精力。

因此在4.0以后,大部分SHE(我怀疑是所有)异常都被标识成破坏性异常,在.NET里,默认情况下CLR不会捕捉它们,而是任由操作系统来处理—即关闭程序,并打开一个错误对话框通知用户。为了保证兼容性,在4.0以前编译的程序,例如在2.0、3.0和3.5编译的程序,依然采用的是老的策略—即.NET会同时捕捉.NET异常和SHE异常。而在4.0下面编译的程序才会使用新的策略,这也是在文章的开头,我的朋友所碰到的问题。你可以在.NET 4.0下面编译下面的程序,体验一下这个新变化:

Program.cs

  1. using System;     
  2. using System.Runtime.InteropServices;       
  3. namespace ConsoleApplication1 {       
  4. class Program     {           
  5. [DllImport("Ref.dll")]           
  6. private extern static void TestMethod();           static void Main(string[] args)          
  7.  {             try             
  8.   {          TestMethod();              
  9.  }               
  10. catch (Exception e)            
  11.    {                 
  12.   Console.WriteLine("Catching exception: {0}", e);         
  13.       }       
  14.     }     } }  

Ref.cpp:

  1. #include "stdafx.h"       
  2. extern "C" __declspec(dllexport) void TestMethod() {            
  3. int *p = NULL;                     
  4.  // 会导致.NET抛出一个AccessViolation异常           
  5.  *p = 10; } 

上面的代码里,Program.cs使用P/Invoke技术调用了Ref.dll文件里的TestMethod,但是TestMethod尝试给一个空指针赋值,导致一个AccessViolation异常。如果你在2.0下面编译program.cs,并执行的话,这个AccessViolation异常会被catch(Exception e)捕捉到,而如果你在4.0下面编译并执行的话,你会发现catch (Exception e)是不能捕捉到这个异常的。

然而并不是所有人都想要这个新的异常机制,如果你的程序是在4.0下面编译并运行,而你又想在.NET程序里捕捉到SHE异常的话,有两个方案可以尝试:

1.   在托管程序的.config文件里,启用legacyCorruptedStateExceptionsPolicy这个属性,即简化的.config文件类似下面的文件:

App.config:

  1. <?xml version="1.0"?> 
  2. <configuration> 
  3.  <startup> 
  4.    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
  5.  </startup> 
  6.     <runtime> 
  7.       <legacyCorruptedStateExceptionsPolicy enabled="true" /> 
  8.     </runtime> 
  9. </configuration> 

这个设置告诉CLR 4.0,整个.NET程序都要使用老的异常捕捉机制。

2.  在需要捕捉破坏性异常的函数外面加一个HandleProcessCorruptedStateExceptions属性,这个属性只控制一个函数,对托管程序的其他函数没有影响,例如:

  1. [HandleProcessCorruptedStateExceptions]     
  2. static void Main(string[] args) {     
  3.   try     {          
  4.  TestMethod();     
  5.   }       
  6. catch (Exception e)    
  7.    {           
  8. Console.WriteLine("Catching exception: {0}", e);   
  9.     } } 

你也可以下载示例代码自己试一下(需要VS 2010才能编译):

http://files.cnblogs.com/killmyday/CSEsample.zip

原文标题:.NET 4.0里异常处理的新机制

链接:http://www.cnblogs.com/killmyday/archive/2010/09/05/1818533.html

【编辑推荐】

  1. 使用ASP.NET 4的自动启动特性
  2. 详解.NET 4.0并行计算支持历史
  3. 详读.NET 4.0环境配置
  4. 详解.NET 4.0中异常处理方面的新特性
  5. 三方面诠释.NET 4.0的新特性
责任编辑:彭凡 来源: 博客园
相关推荐

2020-10-13 08:36:30

React 架构机制

2011-07-15 09:57:03

MongoDB缓存刷新

2021-12-08 06:53:28

Choreograph屏幕机制

2009-01-05 09:14:17

.NETcatch性能损失

2013-08-22 17:10:09

.Net异常处理

2021-04-21 07:53:13

Android屏幕刷新

2010-03-10 11:55:30

Mocha BSM运维管理摩卡软件

2020-09-21 14:35:20

VuenextTick前端

2011-03-17 09:20:05

异常处理机制

2015-12-28 11:25:51

C++异常处理机制

2021-03-02 09:12:25

Java异常机制

2010-06-09 09:18:34

.NET 4并行编程

2016-10-21 09:29:53

嵌入式Linux更新机制

2024-03-04 10:00:35

数据库处理机制

2011-04-06 10:27:46

Java异常处理

2010-04-14 09:20:26

.NET多线程

2010-01-05 09:26:13

.NET 4.0

2011-07-21 15:20:41

java异常处理机制

2018-08-10 04:40:56

2009-02-06 14:11:36

ASP.NET.NET全局异常处理
点赞
收藏

51CTO技术栈公众号