Документация и фактическое поведение CER не совпадают точно на основании того, что я наблюдаю. Проблема, которую вы описываете, когда ThreadAbortException
вводится между Insert
и numAdded++
, невозможна ни с одной из протестированных версий .NET Framework. Для этого есть две возможные причины.
PrepareConstrainedRegions
, несмотря на то, что говорится в документации, оказывает заметное влияние на блок try
. Это задержит определенные инъекции прерывания; особенно те, которые не приходят, когда поток находится в состоянии оповещения.
- Даже при отсутствии вызова
PrepareConstrainedRegions
прерывание все равно не будет введено в это место. На основе кода SSCLI прерывание будет введено при обратном переходе для вращения цикла while
.
Я понял кое-что из этого, когда отвечал на свой собственный вопрос здесь , а затем пытался ответить на вопрос о том, как Thread.Abort
на самом деле работает здесь .
Пункт № 2 недопустим. Это деталь реализации SSCLI, которая может не переноситься на официальные дистрибутивы (хотя я подозреваю, что это действительно так). Кроме того, он игнорирует возможность ввода прерывания в какой-то момент во время выполнения Insert
. Я предполагаю, что вполне возможно, что решающие биты Insert
могли бы использовать CER для внутреннего использования.
Точка № 1, возможно, имеет значение, но напрашивается вопрос, почему Microsoft не документировала это и почему в цитируемой вами статье это тоже не упоминалось. Конечно, автор статьи знал об этом факте. В противном случае я тоже не понимаю, как представленный код может быть безопасным. Другими словами, сейчас это кажется безопасным только случайно.
Если бы мне нужно было угадать, что PrepareConstrainedRegions
делает за кулисами, я бы сказал, что он устанавливает флаг в движке JIT, который говорит ему не вводить обработчик опроса GC, который стратегически размещается в обратной ветви. прыжки для кода внутри блока CER try
. Этот хук опроса GC обычно используется для асинхронного прерывания (в дополнение к его основной цели, связанной со сборкой мусора).