Код, демонстрирующий важность области ограниченного исполнения - PullRequest
38 голосов
/ 09 июля 2009

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

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

Ответы [ 5 ]

45 голосов
/ 29 августа 2009
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 подключается, он пытается создать ConstrainedRegion из блока finally.

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

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

19 голосов
/ 28 августа 2009

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

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

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

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

3 голосов
/ 28 августа 2009

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

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

1 голос
/ 09 июля 2009

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

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

0 голосов
/ 24 августа 2009

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

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

...