Cuando el ejemplo proporcionado se genera en modo de lanzamiento y luego JIT-ed en el código máquina de 64 bits, no contiene suficiente información para que el depurador correlacione el punto de interrupción con cualquier instrucción particular de la máquina. Es por eso que el depurador nunca se detiene en este punto de interrupción durante la ejecución de un código de máquina JIT-ed. Simplemente no sabe dónde parar. Probablemente es algún tipo de mal comportamiento o incluso un error en el depurador CLR de 64 bits porque solo se puede reproducir cuando está JIT-ed en código máquina de 64 bits pero no en código máquina de 32 bits.
Cuando el depurador ve un punto de interrupción en el código, trata de encontrar una instrucción de máquina en el código JIT-ed que corresponde a la ubicación marcada por el punto de interrupción. Primero, necesita encontrar una instrucción IL que corresponda a una ubicación de punto de interrupción en su código C#. Luego necesita encontrar una instrucción de máquina que corresponda al comando IL. Luego establece un punto de corte real en la instrucción de la máquina encontrada y comienza la ejecución del método. En su caso, parece que el depurador simplemente ignora un punto de interrupción porque no puede asignarlo a una instrucción de máquina particular.
El depurador no puede encontrar una dirección de una instrucción de máquina que sigue inmediatamente si ... else. La instrucción if ... else y el código dentro de ella de alguna manera provocan este comportamiento. No importa qué afirmación sigue al si ... else. Puede reemplazar la instrucción Console.WriteLine ("2") con alguna otra y todavía podrá reproducir el problema.
Verá que el compilador C# emite un intento ... atrapa bloque alrededor de la lógica que lee la lista si desmontará el ensamblaje resultante con Reflector. Es una característica documentada del compilador de C#. Puede leer más al respecto en The foreach statement
Un try ... catch ... finally block tiene un efecto bastante invasivo en un código JIT-ed. Utiliza el mecanismo de Windows SEH debajo del capó y reescribe mal tu código. No puedo encontrar un enlace a un buen artículo en este momento, pero estoy seguro de que puedes encontrar uno si estás interesado.
Es lo que sucede aquí. El intento ... finalmente bloquear dentro de la instrucción if ... else hace que el depurador tenga un problema. Puede reproducir su problema con un código muy simple.
bool b = false;
if (b)
{
try
{
b = true;
}
finally
{
b = true;
}
}
else
{
b = true;
}
b = true;
Este código no llama a las funciones externas (que elimina efecto de inlining método propuesto por una de las respuestas) y que compila directamente en IL sin ninguna información adicional codificada añadida por el compilador de C#.
Se puede reproducir solo en modo de lanzamiento porque en el modo de depuración el compilador emite la instrucción IL NOP para cada línea de su código C#. La instrucción IL NOP no hace nada y se compila directamente a la instrucción NOP de la CPU por el JITer que no hace nada también.La utilidad de esta instrucción es que puede ser utilizada por el depurador como un ancla para los puntos de corte, incluso si el resto del código está mal reescrito por el JITer.
Pude hacer que el depurador funcionara correctamente al poner una instrucción NOP justo antes de la instrucción que sigue al if ... else.
Puede leer más sobre las operaciones NOP y proceso de mapeo depurador aquí Debugging IL
Usted puede tratar de utilizar la extensión para WinDbg y SOS para que examine la versión JIT-ed del método. Puede intentar examinar el código de máquina que genera JIT-er e intentar comprender por qué no puede volver a mapear ese código de máquina a una línea particular de C#.
Aquí hay un par de enlaces sobre el uso de WinDbg para romper el código administrado y obtener una dirección de memoria de un método JIT-ed. Creo que deberías poder encontrar la forma de obtener el código JIT-ed para un método desde allí: Setting a breakpoint in WinDbg for Managed Code, SOS Cheat Sheet (.NET 2.0/3.0/3.5).
También puede intentar informar un problema a Microsoft. Probablemente este es un error del depurador CLR.
Gracias por la interesante pregunta.
Tengo esta configuración y no puedo reproducir el comportamiento establecido. ¿Sería importante que estoy usando Win7 64 Bit SP 1? El resto de la configuración es la misma, pero llegué al punto de interrupción todo el tiempo. –
funciona bien para mí - de cualquier manera, ¿por qué estás depurando en modo de lanzamiento? – BrokenGlass
Imagino que la línea ha sido optimizada por el compilador si la pisa, ¿está ejecutando la consola.writeline ("1") dos veces, pero suministrando diferentes argumentos? – forsvarir