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

时间:2009-07-08 23:46:15

标签: c# .net concurrency cer

除非应用了[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)],否则有人会创建一个中断的短样本吗?

我刚刚浏览了这个sample on MSDN,即使我注释掉ReliabilityContract属性,也无法让它中断。最后似乎总是被召唤。

5 个答案:

答案 0 :(得分:44)

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块创建一个ConstrainedRegion。

  • 在没有ReliabilityContract的情况下,不能形成适当的ConstrainedRegion,因此会发出常规代码。在调用Stackoverflow时抛出堆栈溢出异常(在执行try块之后)。

  • 在使用ReliabilityContract的情况下,可以形成ConstrainedRegion,并且可以将finally块中方法的堆栈需求提升到MyFn中。现在,在调用MyFn时抛出堆栈溢出异常(在执行try块之前)。

答案 1 :(得分:19)

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

MSDN Magazine article可能是我见过的最好的描述约束执行环境的技术要求的{{3}}。

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中使用ReliabilityContract方法时,会发生两件事情。该方法将由JIT预先准备,以便它在第一次执行时不会调用JIT编译器,这可能会尝试使用内存本身并导致它自己的异常。此外,在CER内部,运行时承诺不会抛出ThreadAbort异常,并等待在CER完成之后抛出异常。

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

答案 2 :(得分:3)

您是否在调试器下运行MSDN示例?当你在调试器中执行时,我认为CER无法运行,因为调试器本身也会改变执行的性质。

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

答案 3 :(得分:1)

虽然我没有一个具体的例子,但我认为你错过了尝试的方法。最终阻止了保证成功的方法。说该方法总是成功的重点意味着关于在执行期间发生什么(异常)的问题,将采取步骤以确保在方法返回时被访问的数据将处于有效状态。如果没有尝试,最终,您将无法确保任何事情,并且可能意味着您希望发生的操作中只有一半会发生。因此,Cer.Success实际上并不能保证成功,它只表明你作为开发人员保证成功。

查看此页面,了解Success和MayFail状态之间的差异,因为它与Array.CopyTo方法有关:http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

答案 4 :(得分:-5)

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

它们大部分“留作将来使用”。