Подтвердить что ты не робот

Кодекс, демонстрирующий важность ограниченного региона исполнения

Может ли кто-нибудь создать короткий образец, который разбивается, если не применяется [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]?

Я просто просмотрел этот образец в MSDN и не смог его сломать, даже если я прокомментирую атрибут ReliabilityContract. Наконец, кажется, всегда вызываются.

4b9b3361

Ответ 1

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, он пытается создать ConstrainedRegion из блока finally.

  • В случае без ReliabilityContract не может быть сформирован правильный ConstrainedRegion, поэтому выдается обычный код. Исключение выбрасывается при вызове Stackoverflow (после выполнения блока try).

  • В случае с ReliabilityContract может быть сформирован ConstrainedRegion, и требования к стеку методов в блоке finally могут быть сняты в MyFn. Исключение теперь вызывается при вызове MyFn (до того, как блок try будет выполнен).

Ответ 2

Основным драйвером для этой функции было обеспечение строгих требований SQL Server к интеграции CLR в SQL Server 2005. Вероятно, чтобы другие могли использовать и, вероятно, по юридическим причинам, эта глубокая интеграция была опубликована как API хостинга, но технические требования были SQL Server. Помните, что в SQL Server MTBF измеряется не через несколько часов, а перезапуск процесса, потому что необработанное исключение было совершенно неприемлемым.

Эта статья статья журнала MSDN, вероятно, является лучшей из тех, которые я видел, описывая технические требования, для которых была создана среда ограничения.

ReliabilityContract используется для украшения ваших методов, чтобы указать, как они работают с точки зрения потенциально асинхронных исключений (ThreadAbortException, OutOfMemoryException, StackOverflowException). Область ограниченного выполнения определяется как раздел catch или finally (или fault) блока try, которому сразу предшествует вызов 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
}

Когда метод ReliabilityContract используется из CER, есть две вещи, которые случаются с ним. Метод будет предварительно подготовлен JIT, чтобы он не вызывал JIT-компилятор при первом запуске, который мог бы попытаться использовать память и вызвать собственные исключения. Кроме того, в то время как внутри CER среда выполнения promises не бросает исключение ThreadAbort и будет ожидать выброса исключения до завершения CER.

Итак, вернемся к вашему вопросу; Я все еще пытаюсь найти простой пример кода, который будет напрямую отвечать на ваш вопрос. Как вы, возможно, уже догадались, самый простой пример потребует довольно много кода, учитывая асинхронный характер проблемы и, скорее всего, будет кодом SQLCLR, потому что это среда, которая будет использовать ССВ для большей пользы.

Ответ 3

Вы используете образец MSDN в отладчике? Я не думаю, что CER может функционировать, когда вы выполняете в отладчике, поскольку сам отладчик изменяет характер выполнения в любом случае.

Если вы создадите и запустите приложение в режиме оптимизированного выпуска, вы сможете увидеть его сбой.

Ответ 4

Пока у меня нет конкретного примера для вас, я думаю, что вам не хватало точки, чтобы попытаться заблокировать внутри методов, которые гарантируют успех. Все дело в том, что метод всегда будет успешным, означает, что в отношении того, что (исключение) происходит во время выполнения, будут предприняты шаги для обеспечения доступа к данным, которые будут доступны в правильном состоянии при возврате метода. Без попытки... наконец, вы ничего не обеспечивали бы, и это могло означать, что произойдет только половина операций, которые вы хотели совершить. Таким образом, Cer.Success на самом деле не гарантирует успех, он только утверждает, что вы, как разработчик, гарантируете успех.

Ознакомьтесь с этой страницей для объяснения различий между состояниями Success и MayFail, поскольку они относятся к методу Array.CopyTo: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

Ответ 5

Атрибуты CER - это средства документации. Они влияют на то, как CLR будет выполнять код в некоторых ситуациях, но я считаю, что они (или их отсутствие) никогда не приведут к ошибке в текущих версиях .NET.

Они в основном "зарезервированы для будущего использования".