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

Sam*_*ron 38 .net c# concurrency cer

除非应用,否则任何人都可以创建一个断开的短样本[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]吗?

我刚刚在MSDN上运行了这个示例,即使我注释掉ReliabilityContract属性,也无法让它破坏.最后似乎总是被召唤.

jyo*_*ung 45

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当MyFn被jitted时,它会尝试从finally块创建ConstrainedRegion.

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

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

  • 请注意,此代码似乎在StackOverflow异常上正常失败,但实际上并非如此.如果通过删除Big-line来破坏堆栈,并递归调用StackOverflow,则不会触发OOM并且不会捕获SO异常.这是"PrepareConstrainedRegions"(afaik)的限制.又见Richter的CLR书:http://books.google.nl/books?id=QMdCf_mm55cC&pg=PT1016&lpg=PT1016&dq=ExecuteCodeWithGuaranteedCleanup+stackoverflowexception&source=bl&ots=V942WGDtFy&sig=I8shxrKexuEKnJPvQf7Cqzck6SE&hl=en&sa=X&ei=NYnpUI-BI8-S0QX6q4GgAw&redir_esc=y (2认同)

Pet*_*ert 20

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

这篇MSDN杂志文章可能是我见过的最好的一篇文章,描述了为约束执行环境构建的技术要求.

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这并不完全正确。CER 还用于“SafeHandles”以确保它们关闭。这包括导致操作系统 SafeHandle 的任何 P/Invoke(GDI+、文件等)。如果您开始在 Windows 中泄漏句柄,您很快就会遇到麻烦。 (3认同)