zoukankan      html  css  js  c++  java
  • C#的强迫执行域Constrained Execution Regions(CERs)

    强迫执行域(CERs)通常用于遇到未预见的异常时,保证系统被多个AppDomain或者进程共享的状态的正确性。

    这种异常我们通常称之为Asynchronous Exception。比如当调用一个函数时,CLR需要去加载assembly,在AppDomain的堆上创建类型,调用类型的类构造函数,JIT把IL转换成native代码等等。当这些过程出错时,CLR会抛异常。如果这个异常是在代码的catch或者finally抛出的话,catch和finally中的错误恢复代码就不能被执行了,这样系统的状态就有可能会出错。

    考虑如下的代码示例:

     1     sealed class Type1
     2     {
     3         static Type1()
     4         {
     5             // throw new ApplicationException("if this throws an exception, M won’t get called");
     6             Console.WriteLine("Type1's static ctor called");
     7         }
     8 
     9         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    10         public static void M()
    11         {
    12             Console.WriteLine("Type1's M");
    13         }
    14     }
    15 
    16         static void CER()
    17         {
    18             RuntimeHelpers.PrepareConstrainedRegions();
    19             try
    20             {
    21                 Console.WriteLine("In try");
    22             }
    23             finally
    24             {
    25                 // Type1’s static constructor is implicitly called in here
    26                 Type1.M();
    27             }
    28         }

    第9行和第18行使用了CER,需要using System.Runtime.CompilerServices; 和using System.Runtime.ConstrainedExecution;。当JIT编译器看到CERs时,会先编译catch和finally中的代码。JIT会加载需要的assembly,创建对象,调用类构造函数,JIT所有的方法。如果任何一步出了异常,那么这个异常会在try代码块之前抛出,从而保证了系统的状态始终是正确的。

    运行上面的代码,可以得到如下的输出:

    Type1's static ctor called
    In try
    Type1's M
    

     如果注释掉第9行和第18行,得到的输出如下:

    In try
    Type1's static ctor called
    Type1's M
    

    补充几个关于Exception的小知识:


    1. 在watch窗口输入$exception,可以看到CLR的exception信息。对于C++,可以在watch窗口输入@err,hr,相当于显示上一次调用API后再调用GetLastError。输入@eax,hr显示eax寄存器的值,由于win的API的返回值放在eax中,所以这句话的意思就是的到最近一个API的返回值。另外,如果你需要看的是一个array,你可以通过在watch中写 array, 3来看数组的前3个值。
    2. 可以监听AppDomain的FirstChanceException事件来找到exception的第一现场。
    3. 如果想先catch在throw。应该用catch(e){throw;} 而不是 catch(e){throw e;}。
    4. 在函数前加属性[MethodImpl](MethodImplOptions.NoInlining)] 可以强迫JIT在异常抛出时不要inline这个方法。我在之前的博客中介绍过如何使用debugger attribute来定制在Visual Studio中的信息。参见“定制自己的Visual Studio的Debugger Visualizer”和“定制C#在Visual Studio中的debug信息”。
    5. 可以调用 SetErrorMode(SEM_NOGPFAULTERRORBOX) 来禁用Windows Error Reporting,就是出错后问你要不要发送出错信息的那个对话框。

  • 相关阅读:
    C#中一些关联名词的含义归纳
    lua杂记
    项目管理工具与常用网站汇总
    SVN用法及常见问题分析
    递归打印lua中的table
    脚本编辑中的一些名词概念
    quick-cocos2d-x lua框架解析(一)对UI进行操作的UiUtil脚本
    lua的table转为excel表格的方法
    前端mvc与mvvm
    ext--创建store
  • 原文地址:https://www.cnblogs.com/fresky/p/3123818.html
Copyright © 2011-2022 走看看