除非应用了[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
,否则有人会创建一个中断的短样本吗?
我刚刚浏览了这个sample on MSDN,即使我注释掉ReliabilityContract属性,也无法让它中断。最后似乎总是被召唤。
答案 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中导致错误。
它们大部分“留作将来使用”。