.NET 4.0里相当处理的新机制

前些天,有二个爱人问作者怎么在.NET里不可能捕捉(catch)到有的可怜了,而且在调节和测试器里也捕捉不到。研商了一晃,是.NET
4.0里新的可怜处理机制捣的鬼。

SQL Server, 

在.NET 4.0从此,CL昂科威将会有别于出一些百般(都以SEH非凡),将这个卓殊标识为破坏性很是(Corrupted
State Exception)。针对这几个至极,CL大切诺基的catch块不会捕捉这几个极度,固然你用接近上面包车型地铁代码:

            try
            {
                TestMethod();
            }
            catch (Exception e)
            {
                Console.WriteLine(“Catching exception: {0}”, e);
            }

也并未章程捕捉到那个格外。之所以要这么设计,在MSDN的篇章Handling Corrupted State
Exceptions
里早已涉嫌了。即,有一部分扶助插件的次第,例如Visual
Studio大概SQL Server,它们支持调用托管代码编写成的插件,可是它们自个儿作者有过多代码是由非托管的C++写成的。由于插件平时会调用到非托管的API,而众多时光,这一个插件的代码根本就不知晓怎样处理非托管的API抛出来的SEH相当。在4.0在先,因为SEH格外被转换到了跟普通.NET很是相同的不胜,那样程序员只要用catch
( Exception e)的格局就能够捕捉到全部的丰富。这样处理的难点是,由于SEH相当常常都不是托管代码抛出的,托管代码根本就不清楚SEH非常被扔出来的缘由,简单的catch (
Exception e)处理使得整个程序会处在3个要命不安宁的景观,使得后面被忽视的难点在末端以更要紧的不二法门出现— 例如保存被损坏的数目。那样,看起来使用catch
( Exception e)处理全部的尤其的方法非常的粗略,但事实上让程序员大概用户在题材延后产生时,分析起来要求开销越多的肥力。

 

故此在4.0后头,超越叁分一SEH(小编难以置信是负有)格外都被标识成破坏性极度,在.NET里,暗中同意意况下CL君越不会捕捉它们,而是任由操作系统来拍卖—即关闭程序,并开拓一个谬误对话框通告用户。为了保障兼容性,在4.0原先编译的先后,例如在2.0、3.0和3.5编写翻译的主次,如故选择的是老的方针—即.NET会同时捕捉.NET非常和SEH很是。而在4.0底下编写翻译的次第才会使用新的国策,那也是在作品的上马,笔者的心上人所碰着的题材。你可以在.NET
4.0上边编写翻译上边包车型大巴先后,体验一下以此新转变:

Program.cs:

using System;
   using System.Runtime.InteropServices;
  
   namespace ConsoleApplication1
 {
     class Program
     {
         [DllImport("Ref.dll")]
         private extern static void TestMethod();
  
         static void Main(string[] args)
         {
             try
             {
                 TestMethod();
             }
             catch (Exception e)
             {
                 Console.WriteLine("Catching exception: {0}", e);
             }
         }
     }
 }

 

 

Ref.cpp:

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

 

下面的代码里,Program.cs使用P/Invoke技术调用了Ref.dll文件里的TestMethod,可是TestMethod尝试给3个空指针赋值,导致三个AccessViolation相当。借使您在2.0下边编译program.cs,并履行的话,这一个AccessViolation相当会被catch(Exception e)捕捉到,而一旦你在4.0下边编写翻译并施行的话,你会意识catch
(Exception e)是不能够捕捉到那一个万分的。

 

不过并不是全部人都想要这几个新的老大机制,即使您的次第是在4.0底下编写翻译并运营,而你又想在.NET程序里捕捉到SEH非凡的话,有多个方案得以尝尝:

1.         在托管程序的.config文件里,启用legacyCorruptedStateExceptionsPolicy那一个脾性,即简化的.config文件类似上边包车型大巴文书:

 

App.config:

<?xml version="1.0"?>
<configuration>
 <startup>
   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
 </startup>
    <runtime>
      <legacyCorruptedStateExceptionsPolicy enabled="true" />
    </runtime>
</configuration>

 

那几个设置告诉CL讴歌MDX 4.0,整个.NET程序都要利用老的老大捕捉机制。

 

2.         在需求捕捉破坏性分外的函数外面加一个HandleProcessCorruptedStateExceptions属性,那性格格只控制1个函数,对托管程序的别的函数没有影响,例如:

[HandleProcessCorruptedStateExceptions]
   static void Main(string[] args)
 {
     try
     {
         TestMethod();
     }
     catch (Exception e)
     {
         Console.WriteLine("Catching exception: {0}", e);
     }
 }

 

你也能够下载示例代码本人试一下(需求VS
二〇〇九才能编写翻译):

/Files/killmyday/CSEsample.zip

相关文章