代码之家  ›  专栏  ›  技术社区  ›  Sam Saffron James Allen

演示受约束执行区域重要性的代码

  •  37
  • Sam Saffron James Allen  · 技术社区  · 16 年前

    有人能创造一个 短样品 它会断裂,除非 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 应用吗?

    我刚跑过这个 sample on MSDN 即使我对ReliabilityContract属性进行了注释,也无法让它中断。最后似乎总是接到电话。

    5 回复  |  直到 9 年前
        1
  •  44
  •   Sam Saffron James Allen    16 年前
    using System;
    using System.Runtime.CompilerServices;
    using System.Runtime.ConstrainedExecution;
    
    class Program {
        static bool cerWorked;
    
        static void Main( string[] args ) {
            try {
                cerWorked = true;
                MyFn();
            }
            catch( OutOfMemoryException ) {
                Console.WriteLine( cerWorked );
            }
            Console.ReadLine();
        }
    
        unsafe struct Big {
            public fixed byte Bytes[int.MaxValue];
        }
    
        //results depends on the existance of this attribute
        [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] 
        unsafe static void StackOverflow() {
            Big big;
            big.Bytes[ int.MaxValue - 1 ] = 1;
        }
    
        static void MyFn() {
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                cerWorked = false;
            }
            finally {
                StackOverflow();
            }
        }
    }
    

    当myfn被jitted时,它试图从finally块创建一个约束区域。

    • 在没有可靠合同的情况下,无法形成适当的约束区域,因此会发出常规代码。对stack overflow的调用(在执行try块之后)会引发堆栈溢出异常。

    • 在可靠性合同的情况下,可以形成一个约束区域,并将最终块中方法的堆栈要求提升到myfn中。现在,对myfn的调用会引发堆栈溢出异常(在执行try块之前)。

        2
  •  19
  •   Andrew Savinykh    9 年前

    此功能的主要驱动程序是支持SQL Server将CLR集成到SQL Server 2005中的严格要求。可能是为了让其他人可以使用,而且出于法律原因,这种深度集成被发布为宿主API,但技术要求是SQL服务器。请记住,在SQL Server中,MTBF是以月而不是小时来度量的,并且由于发生未处理的异常而重新启动进程是完全不可接受的。

    这个 MSDN Magazine article 可能是我见过的描述受限执行环境所针对的技术需求的最好的一个。

    ReliabilityContract用于修饰您的方法,以指示它们如何根据潜在的异步异常(ThreadAbortException、OutOfMemoryException、StackOverflowException)进行操作。受约束的执行区域定义为try块的catch或finally(或fault)部分,该部分前面紧跟对System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions()的调用。

    System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions();
    try 
    {
        // this is not constrained
    } 
    catch (Exception e) 
    {
        // this IS a CER
    } 
    finally 
    {
        // this IS ALSO a CER
    }
    

    当从CER中使用可靠性控制方法时,会发生两件事。该方法将由JIT预先准备好,这样它就不会在第一次执行时调用JIT编译器,而这可能会尝试使用内存本身并导致自己的异常。此外,在CER内部,运行时承诺不会抛出ThreadAbort异常,并将等待抛出异常,直到CER完成。

    所以回到你的问题上来;我仍然在尝试想出一个简单的代码示例,它将直接回答你的问题。正如您可能已经猜到的那样,考虑到问题的异步性质,最简单的示例将需要相当多的代码,而且很可能是sqlcr代码,因为这是一个将使用CER以获得最大利益的环境。

        3
  •  3
  •   jrista    16 年前

    是否在调试器下运行msdn示例?我认为当您在调试器中执行时,CER不可能运行,因为调试器本身无论如何都会改变执行的性质。

    如果你在优化的发布模式下构建和运行应用程序,你应该能够看到它失败。

        4
  •  1
  •   Relster    16 年前

    虽然我没有一个具体的例子给你,但我认为你错过了尝试的要点……最后,在确保成功的方法中进行阻塞。要说方法总是成功,就意味着在执行过程中发生了什么(异常),将采取措施确保在方法返回时被访问的数据处于有效状态。如果没有尝试……最后,你将无法确保任何事情,也可能意味着你希望执行的操作只有一半会发生。因此,cer.success并不能真正保证成功,它只说明作为开发人员,你是在保证成功。

    请查看此页面,以了解与array.copyto方法相关的成功和可能失败状态之间的差异的解释: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

        5
  •  -5
  •   ima    16 年前

    CER属性是文档的手段。它们确实会影响CLR在某些情况下执行代码的方式,但我相信它们(或缺少它们)永远不会导致.NET的当前版本出错。

    它们大多是“留作将来使用”。

    推荐文章