c# - practices - Código que demuestra la importancia de una Región de Ejecución Restringida
generate documentation c# (5)
¿Alguien podría crear una muestra corta que se rompa, a menos que se aplique [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
?
Acabo de ejecutar esta muestra en MSDN y no puedo hacer que se rompa, incluso si comento el atributo ReliabilityContract. Finalmente parece que siempre se llama.
¿Está ejecutando el ejemplo de MSDN debajo del depurador? No creo que sea posible que CER funcione cuando se está ejecutando dentro del depurador, ya que el depurador mismo cambia la naturaleza de la ejecución de todos modos.
Si compila y ejecuta la aplicación en modo de lanzamiento optimizado, debería poder ver que falla.
El principal impulsor para esta funcionalidad era admitir los requisitos estrictos de los Servidores SQL para integrar el CLR en SQL Server 2005. Probablemente para que otros pudieran usar y probablemente por razones legales, esta integración profunda se publicó como API de alojamiento pero los requisitos técnicos eran Servidores SQL. Recuerde que en SQL Server, MTBF se mide en meses, no en horas, y el proceso de reinicio debido a que se produjo una excepción no controlada es completamente inaceptable.
Este artículo de MSDN Magazine es probablemente el mejor que he visto para describir los requisitos técnicos para los que se creó el entorno de ejecución restringido.
El ReliabilityContract se utiliza para decorar sus métodos para indicar cómo operan en términos de excepciones potencialmente asincrónicas (ThreadAbortException, OutOfMemoryException, Exception). Una región de ejecución restringida se define como una sección de captura o finalmente (o falla) de un bloque de prueba que está inmediatamente precedida por una llamada a 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
}
Cuando se usa un método de ReliabilityContract desde un CER, hay dos cosas que le suceden. El método será preparado previamente por el JIT para que no invoque el compilador JIT la primera vez que se ejecute, lo que podría tratar de usar la memoria y provocar sus propias excepciones. Además, mientras se encuentra dentro de un CER, el tiempo de ejecución promete no arrojar una excepción ThreadAbort y esperará a lanzar la excepción hasta que se haya completado el CER.
Así que de vuelta a tu pregunta; Todavía estoy tratando de encontrar una muestra de código simple que responda directamente a su pregunta. Sin embargo, como ya habrá adivinado, la muestra más simple requerirá bastante código dada la naturaleza asíncrona del problema y probablemente sea un código SQLCLR porque ese es el entorno que utilizará las RCE para obtener el mayor beneficio.
Los atributos CER son medios de documentación. Influyen en cómo CLR ejecutará el código en algunas situaciones, pero creo que (o la falta de ellas) nunca generará un error en las versiones actuales de .NET.
En su mayoría están "reservados para uso futuro".
Si bien no tengo un ejemplo concreto para ti, creo que te estás perdiendo el punto de probar ... por último bloquear dentro de los métodos que garantizan el éxito. El hecho de decir que el método siempre tendrá éxito significa que, en relación con qué (excepción) ocurre durante la ejecución, se tomarán medidas para garantizar que los datos a los que se accede estarán en un estado válido cuando el método retorne. Sin el intento ... por último, no estarías asegurando nada, y podría significar que solo pasaría la mitad de las operaciones que querías que suceda. Por lo tanto, Cer.Success en realidad no garantiza el éxito, solo establece que usted como desarrollador garantiza el éxito.
Consulte esta página para obtener una explicación de las diferencias entre los estados Success y MayFail en lo que respecta a un método Array.CopyTo: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx
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 () {
Big big;
big.Bytes[ int.MaxValue - 1 ] = 1;
}
static void MyFn() {
RuntimeHelpers.PrepareConstrainedRegions();
try {
cerWorked = false;
}
finally {
();
}
}
}
Cuando MyFn está jodido, intenta crear una Restricción del bloque finally.
En el caso sin el ReliabilityContract, no se podría formar una Restricción Limitada adecuada, por lo que se emitirá un código regular. La excepción de desbordamiento de pila se lanza en la llamada a (después de que se ejecuta el bloque try).
En el caso de ReliabilityContract, se podría formar una Restricción limitada y los requisitos de apilamiento de los métodos en el bloque finally podrían elevarse a MyFn. La excepción de desbordamiento de pila se inicia ahora en la llamada a MyFn (antes de que se ejecute alguna vez el bloque try).