2012-01-26 9 views
6

Visual Studio tiene una característica determinada que facilita enormemente la depuración de excepciones no controladas: se detiene en la línea ofensiva del código y muestra la excepción.¿Puedo detener Visual Studio en excepciones no controladas dentro del código de la tarea?

Parece que la clase Task está diseñada de tal manera que esta característica siempre se suprime: capta todas las excepciones y luego vuelve a lanzar una excepción diferente cuando la tarea está Wait ed o finalizada.

Sé que puedo hacer que se detenga en las excepciones de primera oportunidad, pero esto no siempre ayuda: imagine que se producen varias excepciones manejadas del mismo tipo antes que la no controlada. En este caso, VS se detendrá en cada excepción no problemática además de la que realmente causa el problema.

Otra alternativa es aún menos aceptable: simplemente mirando el rastro de la pila del InnerException: esto significa que aunque sé qué línea causó la excepción, no puedo acceder a su estado local, como podría si el programa fuera en realidad se detuvo allí.

¿De alguna manera puedo obtener lo mejor de ambos mundos, usando la clase Task pero sin tener que vivir con el conjunto de funciones de depuración de excepciones degradadas?


Bono pregunta: ¿significa esto que una excepción de referencia nula dentro de un bloque de await no hará que Visual Studio para detener allí mismo, pero en su lugar dejar en otro lugar por completo?

+2

El método privado Task.Execute() contiene la instrucción catch everything. HandleException y AddException después de eso. Todo es privado y no virtual. –

+0

@HansPassant si desea publicar eso como una respuesta (lo que implica que esto es imposible, básicamente), eventualmente lo aceptaré en ausencia de mejores respuestas. –

Respuesta

3

El tipo Task ajusta todas las excepciones en AggregateException. Sin embargo, si está utilizando la funcionalidad async/await, cuando await a Task, la excepción interna se desenvuelve y se vuelve a lanzar, conservando el rastro original de la pila.

VS11 tendrá mejor soporte para la eliminación de errores async, pero no creo que sea posible llegar tan lejos como lo que espera. Task es todo sobre código concurrente y asíncrono, y es por eso que no creo que esto funcione alguna vez.

Considere, por ejemplo, si tiene un Task ejecutándose en un hilo del grupo de subprocesos que va a await. Puede await en un bloque try para detectar una excepción de la Task ... o puede await fuera de un bloque try, dejando a excepción del Task 's para ser controlada.

El punto con ese ejemplo es que cuando se produce la excepción, el depurador no sabe si la excepciónserá no controlada. Con el código síncrono, tan pronto como se lanza la excepción, se comprueba la pila, y si no se controla, el depurador sabe que no se ha manejado y puede tomar una acción especial de inmediato (incluso antes de que la pila se desenrolle).

Por lo tanto, no creo que sea posible hacer lo que quiera. Sin embargo, puedes acercarte bastante con IntelliTrace (solo en VS Ultimate).

+2

Entiendo que está atrapado porque no se puede saber si algo va a querer mirarlo _ fuera de la tarea. Pero no diría que lo que quiero es, fundamentalmente, imposible; simplemente no está implementado. No hay ninguna razón por la que Task no pueda tener 'TaskCreationOption.LeaveExceptionsAlone'. 'async' no especificaría esa opción para obtener las características que quiere; Lo especificaría para obtener las características que quiero. Por desgracia, eso no forma parte de la implementación actual. –

Cuestiones relacionadas