受约束的执行区域

受约束的执行区域(CER)是创作可靠托管代码的机制的一部分。 CER 定义了一个区域,其中公共语言运行时(CLR)被限制以避免抛出带外的异常,这些异常将使该区域内的代码无法完全执行。 在该区域中,用户代码被限制,无法执行可能引发带外异常的代码。 该PrepareConstrainedRegions方法必须紧接在try块之前,并将catchfinallyfault块标记为受约束的执行区域。 标记为受约束区域后,代码只能调用具有强可靠性协定的其他代码,并且代码不应分配或对未准备或不可靠的方法进行虚拟调用,除非代码准备处理故障。 CLR 会延迟对在 CER 中执行代码的线程中止操作。

重要

CER 仅在 .NET Framework 中受支持。 本文不适用于 .NET Core 或 .NET 5 及更高版本。

除带批注 try 块外,约束的执行区域还以 CLR 中的不同形式使用,尤其是在派生自 CriticalFinalizerObject 类的类中执行的关键终结器以及使用 ExecuteCodeWithGuaranteedCleanup 该方法执行的代码。

CER 事先准备

CLR 事先准备 CER 以避免出现内存不足的情况。 需要预先准备,因此 CLR 不会在实时编译或类型加载期间导致内存不足的情况。

开发人员需要指示代码区域是 CER:

约束

用户可以在 CER 中编写的代码类型中受到约束。 该代码不会导致带外的异常,例如,可能由以下操作导致:

  • 显式分配。

  • 拳击。

  • 获取锁。

  • 虚拟调用未准备好的方法。

  • 调用弱可靠性协定或不存在可靠性协定的方法。

在 .NET Framework 版本 2.0 中,这些约束是准则。 诊断通过代码分析工具提供。

可靠性协定

ReliabilityContractAttribute这是一个自定义属性,用于记录给定方法的可靠性保证和损坏状态。

可靠性保证

可靠性保证(由 Cer 枚举值表示)指示给定方法的可靠性程度:

  • MayFail。 在特殊情况下,该方法可能会失败。 在这种情况下,该方法会向调用者报告其成功或失败的情况。 该方法必须包含在 CER 中,以确保它可以报告返回值。

  • None。 方法、类型和程序集没有 CER 的概念,如果状态损坏没有得到实质性的缓解,在 CER 内进行调用很可能是不安全的。 它不利用 CER 保证。 这意味着:

    1. 在特殊情况下,该方法可能会失败。

    2. 方法可能报告失败,也可能不报告失败。

    3. 该方法并不是为了使用 CER 而编写的,这种情况是最有可能发生的。

    4. 如果方法、类型和程序集没有显示标识为成功,则会隐式标识为 None

  • Success。 在特殊情况下,该方法可以保证成功。 为了实现这种可靠性级别,应始终围绕调用的方法构造 CER,即使从非 CER 区域中调用它也是如此。 方法是否成功取决于它是否完成了预期目标,尽管成功的定义可以是主观的。 例如,标记 Count 为 ReliabilityContractAttribute(Cer.Success) 意味着在 CER 下运行时,它始终返回 ArrayList 中元素数量的计数,并且永远不会使内部字段处于不确定的状态。 但是,CompareExchange 方法也标记为成功,此处的成功意味着该值不会因争用条件而替换为新值。 关键点是,该方法的行为方式与文档中描述的相符,并且不需要编写 CER 代码来处理任何超出正确但不可靠代码表现的异常行为。

腐败程度

损坏级别由 Consistency 枚举值表示,指示给定坏境中状态的损坏程度:

  • MayCorruptAppDomain。 在特殊情况下,公共语言运行时(CLR)无法保证当前应用程序域中的状态一致性。

  • MayCorruptInstance。 在特殊情况下,此方法保证将状态损坏限制在当前实例。

  • MayCorruptProcess,在特殊情况下,CLR 不保证状态一致性:也就是说,条件可能会损坏进程。

  • WillNotCorruptState。 在异常情况下,此方法保证不会损坏状态。

可靠性 try/catch/finally

可靠性 try/catch/finally 是一种异常处理机制,其可预测性保证级别与非托管版本相同。 catch/finally 块为 CER。 块中的方法需要预先准备,并且必须不可中断。

在 .NET Framework 2.0 版中,代码通过在 try 块之前直接调用 PrepareConstrainedRegions 来通知运行时 try 是可靠的。 PrepareConstrainedRegions 是编译器支持类的成员 RuntimeHelpers。 在其通过编译器变得可用之前,直接调用 PrepareConstrainedRegions

不可中断的区域

不可中断的区域将一组指令分组到 CER 中。

在 .NET Framework 2.0 版中,通过使用编译器支持暂停可用性,用户代码创建不可中断的区域,其中具有包含前面是 PrepareConstrainedRegions 方法调用的空 try/catch 块的可靠 try/catch/finally。

关键终结器对象

CriticalFinalizerObject 保证垃圾回收会执行终结器。 进行分配时,应事先准备好终结器及其调用关系图。 终结器方法在 CER 中执行,并且必须遵从所有关于 CER 和终结器的约束。

任何继承自SafeHandleCriticalHandle的类型都保证其终结器在 CER 中执行。 在 ReleaseHandle 派生的类中实现 SafeHandle 以执行释放图柄所需的任何代码。

CER 中不允许的代码

CER 中不允许以下操作:

  • 显示分配。

  • 获取锁。

  • 拳击。

  • 多维数组访问。

  • 通过反射进行的方法调用。

  • EnterLock

  • 安全检查。 不执行请求,仅链接请求。

  • COM 对象和代理的 IsinstCastclass

  • 获取或设置透明代理上的字段。

  • 序列化。

  • 函数函数指针和委托。

另请参阅