C# 了解本例中CER的目的

C# 了解本例中CER的目的,c#,list,cer,C#,List,Cer,我正在通读,试图理解受约束的执行区域,但在理解以下示例时遇到一些问题: RuntimeHelpers.PrepareConstrainedRegions(); try { // Prepare my backout code MethodInfo m = _list.GetType().GetMethod("RemoveAt", new Type[] { typeof(int) }); RuntimeHelpers.PrepareMethod(m.MethodHandle

我正在通读,试图理解受约束的执行区域,但在理解以下示例时遇到一些问题:

RuntimeHelpers.PrepareConstrainedRegions();
try {
    // Prepare my backout code
    MethodInfo m = _list.GetType().GetMethod("RemoveAt", new Type[] { typeof(int) });
    RuntimeHelpers.PrepareMethod(m.MethodHandle);

    IEnumerator en = c.GetEnumerator();
    while(en.MoveNext()) {
        _list.Insert(index++, en.Current);
        // Assuming that these lines aren't reordered.
        numAdded++;
    }
    _version++;
}
catch(Exception) {
    // Reliable backout code
    while(numAdded > 0) {
        _list.RemoveAt(index--);
        numAdded--;
    }
    throw;
}
我的理解是
try
块是不受约束的,只有finally和catch块受约束。这意味着在
try
块期间,可以随时抛出异步异常(例如ThreadAbortException),特别是可以在
numAdded++
之前但在
\u list.Insert之后抛出。在这种情况下,回退代码将从
\u列表中删除太少的一项

鉴于此,我很难理解本例中受约束执行区域的用途


我对这一点的理解是正确的还是遗漏了什么?

根据我的观察,CER的文件和实际行为并不完全相符。您描述的
ThreadAbortException
Insert
numAdded++
之间被注入的问题在我测试过的任何.NET Framework版本中都不可能出现。这可能有两个原因

  • PrepareConstrainedRegions
    try
    块有明显的影响,不管文档怎么说。它将延迟某些中止注射;特别是那些在线程处于可警报状态时未出现的线程
  • 即使在没有
    PrepareConstrainedRegions
    调用的情况下,中止仍然不会被注入到该位置。根据SSCLI代码,将在向后跳转时注入中止,以在
循环时旋转


我在回答自己的相关问题,然后试图回答一个关于
Thread.Abort
如何实际工作的问题时,发现了其中的一些问题

第二点是不合法的。这是SSCLI的一个实现细节,可能不会遗留到官方发行版中(尽管我怀疑它确实存在)。此外,它忽略了在执行
Insert
期间在某个点注入中止的可能性。我想,
Insert
的关键部分可能会在内部使用CER

第#1点可能很重要,但这引出了一个问题:为什么微软没有记录它,为什么你引用的文章也没有提到它。这篇文章的作者肯定知道这个事实。否则,我也不理解呈现的代码如何可能是安全的。换言之,目前看来只有在偶然的情况下才是安全的


如果我不得不猜测
PrepareConstrainedRegions
在幕后做了什么,我会说它在JIT引擎中设置了一个标志,告诉它不要注入GC轮询钩子,该钩子策略性地放置在CER
try
块中向后分支跳转的代码中。这个GC轮询钩子是异步中止通常被注入的地方(除了它与垃圾收集相关的主要用途之外)

看起来这里肯定有问题。