Pergunta

Alguém poderia criar um Exemplo de curto que as quebras, a menos que o [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] é aplicada?

Eu corri através deste no MSDN e sou incapaz de obtê-lo de quebrar, mesmo se eu comentar o atributo ReliabilityContract. Finalmente parece ficar sempre chamado.

Foi útil?

Solução

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();
        }
    }
}

Quando MyFn é JITted, ele tenta criar um ConstrainedRegion do bloco finally.

  • No caso sem a ReliabilityContract, não ConstrainedRegion adequada poderia ser formado, por isso, um código regular é emitido. A exceção de estouro de pilha é lançada sobre a chamada para Stackoverflow (após o bloco try é executado).

  • No caso da ReliabilityContract, um ConstrainedRegion pode ser formado e as exigências da pilha de métodos na finalmente bloco pode ser levantada em MyFn. A exceção de estouro de pilha é agora lançada sobre a chamada para MyFn (antes do bloco try é sempre executada).

Outras dicas

O principal motor para essa funcionalidade era apoiar servidores SQL rigorosos requisitos para integrar o CLR em SQL Server 2005. Provavelmente para que outros pudessem usar e, provavelmente, por razões legais esta integração profunda foi publicado como uma API de hospedagem, mas os requisitos técnicos foram servidores SQL. Lembre-se que no SQL Server, MTBF é medido em não meses horas eo processo de reiniciar porque uma exceção não tratada aconteceu é completamente inaceitável.

Este MSDN artigo da revista é provavelmente o melhor que eu já vi que descreve os requisitos técnicos do ambiente de execução restrito foi construído.

O ReliabilityContract é usado para decorar seus métodos para indicar como eles operam em termos de exceções potencialmente assíncronos (ThreadAbortException, OutOfMemoryException, StackOverflowException). Uma região de execução restrita é definido como um prendedor ou finalmente (ou falha) da secção de um bloco de teste, que é imediatamente precedida por uma chamada para 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
}

Quando um método ReliabilityContract é usada de dentro de uma CER, existem 2 coisas que acontecem com ele. O método será pré-preparado pelo JIT para que ele não invocará o compilador JIT a primeira vez que é executado o que poderia tentar própria memória uso e porque é próprias exceções. Além disso, enquanto no interior de uma CER as promessas de tempo de execução para não lançar uma exceção ThreadAbort e vai esperar para lançar a exceção até depois do CER foi concluída.

Então, de volta à sua pergunta; Eu ainda estou tentando chegar a uma amostra de código simples que irá responder diretamente sua pergunta. Como você já deve ter adivinhado, porém, a amostra mais simples vai exigir um monte de código, dada a natureza assíncrona do problema e provavelmente será código SQLCLR, porque isso é o ambiente que irá utilizar RCE para o máximo benefício.

Você está executando a amostra MSDN sob o depurador? Eu não acho que é possível para CER a função quando você está executando dentro do depurador, como o próprio depurador muda a natureza da execução de qualquer maneira.

Se você criar e executar o aplicativo no modo de versão otimizada, você deve ser capaz de vê-lo falhar.

Enquanto eu não tenho um exemplo concreto para você, eu acho que você está perdendo o ponto de ter um bloco try..finally dentro dos métodos que o sucesso de garantia. Toda a ponto de dizer que o método sempre terá êxito meios que diz respeito do que (exceção) acontece durante a execução, serão tomadas medidas para garantir que os dados que estão sendo acessados ??estará em um estado válido quando o método retorna. Sem a try..finally, você não estaria garantindo nada, e poderia significar que apenas metade das operações que você queria que acontecesse, iria acontecer. Assim, Cer.Success na verdade não garantia de sucesso, ele só afirma que você, como o desenvolvedor está garantindo o sucesso.

Confira esta página para obter uma explicação sobre as diferenças entre o sucesso eo MayFail afirma que se refere a um método Array.CopyTo: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

atributos CER são meios de documentação. Eles fazem influenciam como CLR irá executar código em algumas situações, mas eu acredito que eles (ou a falta deles) não resultará em erro nas versões atuais do .NET.

Eles são na sua maioria 'reservado para uso futuro'.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top