2008-09-18 10 views
14

Tengo una aplicación Silverlight 2 que consume un servicio WCF. Como tal, utiliza devoluciones de llamada asincrónicas para todas las llamadas a los métodos del servicio. Si el servicio no se está ejecutando, o falla, o la red no funciona, etc. antes o durante una de estas llamadas, se genera una excepción como era de esperar. El problema es que no sé cómo atrapar esta excepción.¿La mejor manera de atrapar una excepción de WCF en Silverlight?

  • Debido a que es una llamada asincrónica, no puedo envolver mi comienzan llamada con un bloque try/catch y tienen que recoger una excepción que sucede después de que el programa ha pasado de ese punto.

  • Como el proxy de servicio se genera automáticamente, no puedo poner un bloque try/catch en todas y cada una de las funciones generadas que llaman a EndInvoke (donde realmente aparece la excepción). Estas funciones generadas también están rodeadas por un código externo en la pila de llamadas, por lo que no hay ningún otro lugar en la pila para probar/atrapar.

  • No puedo poner el try/catch en mis funciones de devolución de llamada, porque la excepción ocurre antes de que se llamaran.

  • Hay una función Application_UnhandledException en mi App.xaml.cs, que captura todas las excepciones no controladas. Podría usar esto, pero parece una manera desordenada de hacerlo. Prefiero reservar esta función para los errores verdaderamente inesperados (también conocidos como errores) y no terminar con el código en esta función para cada circunstancia con la que me gustaría tratar de una manera específica.

¿Falta una solución obvia? ¿O estoy atrapado usando Application_UnhandledException?

[Editar]
Como se menciona a continuación, la propiedad Error es exactamente lo que estaba buscando. Lo que me está arrojando por un bucle es que el hecho de que se lanza la excepción y parece no haber sido detectada, sin embargo, la ejecución puede continuar. Desencadena el evento Application_UnhandledException y hace que VS2008 interrumpa la ejecución, pero continuar en el depurador permite que la ejecución continúe. No es realmente un problema, simplemente parece extraño.

Respuesta

12

Compruebo la propiedad Error de los eventos args en el método de servicio gestor de eventos completado. No he tenido problemas con que no se haya llamado al controlador de eventos. En el caso de que el servidor se caiga, la llamada tarda unos segundos y luego vuelve con una excepción de protocolo en la propiedad Error.

Suponiendo que haya intentado esto y su devolución de llamada realmente nunca se llama, puede buscar la personalización de la clase de proxy generada. Ver this article.

+0

Solo para aclarar, "devolución de llamada de método de servicio" significa evento completado de método, que no es una devolución de llamada. Las rellamadas se usan con APM, mientras que Silverlight usa el EAP. –

+0

De acuerdo. Actualizado en consecuencia. – dcstraw

5

Encontré a forum thread que estaba hablando de esto, y menciona que la mejor práctica es usar la propiedad Error. Entre este hilo y mis propias experiencias, esto es lo que puedo concluir:

  • En .NET código normal, la clase de proxy generada controla la excepción adecuadamente poniendo la excepción en la propiedad de error en lugar de tirarlo.

  • En Silverlight, la clase proxy generada establece la propiedad Error, pero no maneja la excepción por completo. La excepción es recogida por el depurador, que aparece el cuadro de excepción con el mensaje "ProtocolException no fue manejado por el código de usuario". A pesar de este mensaje, la excepción no parece llegar realmente a la función Application_UnhandledException.

Espero que esta sea una de las cosas que arreglarán en el lanzamiento final.

Por el momento, utilizaré la propiedad Error y me ocuparé de la ejecución de la depuración del depurador. Si se vuelve demasiado molesto, puedo desactivar el break on exception para ProtocolException.

0

Usted puede olvidarse de Application_UnhandledException en devoluciones de llamada de cliente Asyn, razón por la cual:

Application_UnhandledException únicas excepciones dispararon en el hilo de interfaz de usuario puede ser atrapado por Application.UnhandledExceptions

Esto significa ... no se llama al todo para una llamada asíncrona WCF :-).

Comprobar respuesta detallada de MSFT

http://silverlight.net/forums/t/21828.aspx

Hola, únicas excepciones disparados en el hilo de interfaz de usuario puede ser atrapado por Application.UnhandledExceptions. No puede detectar excepciones de otros hilos. Puede intentarlo para solucionar el problema: en Visual Studio, desde el menú Depurar, seleccione Excepciones. Luego, verifique "Excepciones de Common Language Runtime". Esto hará que el depurador se detenga cada vez que se lanza una excepción. Pero tenga en cuenta que a veces puede ser bastante molesto, incluso si ya se ha capturado una excepción. Puede usar CheckBoxes para filtrar las excepciones que desea capturar.

Buenas noticias en mi caso es que manejar el mensaje de error solo en la llamada de servicio de clietn es suficiente si no está depurando.

Gracias

Braulio 
+3

Este no es el caso. Definitivamente toco Application_UnhandledExceptions cuando la excepción se origina en el servicio WCF. Puedo decirlo porque puedo verificar fácilmente la FaultException que se lanzó. – Rire1979

0

Oopps ....

Lo sentimos respuesta equivocada de mi lado (así que el tipo MSFT no golpeó el servicio de respuesta de escritura devoluciones de llamada se denominan en el mismo subproceso de interfaz de usuario), la cosa es

Más información:

- In development even detaching from the debugger, this method is never reached. 
- On the production environment yes. 

Mi conjetura algo relacionado con Visu al Studio opciones e interceptando excepciones.

Más información, en este hilo http://silverlight.net/forums/p/48613/186745.aspx#186745

tema muy interesante.

0

No soy fontanero, así que decidí crear mi propia clase de servicio WCF que anula algunas de las funcionalidades del archivo de clase "reference.cs" que automáticamente genera Visual Studio, luego agregué mi propio intento/atrapar bloques para detectar errores de comunicación.

La clase que he creado se ve algo como esto:

public class myWCFService : MyWCFServiceClient 
{ 

    protected override MyController.MyService.IMyWCFService CreateChannel() 
    { 
     return new MyWCFServiceClientChannel(this); 
    } 

} 

private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService 
{ 
    /// <summary> 
    /// Channel Constructor 
    /// </summary> 
    /// <param name="client"></param> 
    public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) : 
    base(client) 
    { 
    } 
    /// <summary> 
    /// Begin Call To RegisterUser 
    /// </summary> 
    /// <param name="memberInformation"></param> 
    /// <param name="callback"></param> 
    /// <param name="asyncState"></param> 
    /// <returns></returns> 
    public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState) 
    {    
     object[] _args = new object[1]; 
     _args[0] = memberInformation; 
     System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState); 
     return _result;    
    } 
    /// <summary> 
    /// Result from RegisterUser 
    /// </summary> 
    /// <param name="result"></param> 
    /// <returns></returns> 
    public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result) 
    { 
     try 
     { 
      object[] _args = new object[0]; 
      MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result))); 
      return _result; 
     } 
     catch (Exception ex) 
     { 
      MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation(); 
      _result.ValidationInformation.HasErrors = true; 
      _result.ValidationInformation.Message = ex.Message; 
      return _result; 
     } 
    } 
} 
+1

¿Por qué hacer todo este esfuerzo, solo para descartar todas las partes de la excepción que no sean la propiedad Mensaje? Casi nunca es una buena idea tirar la información. –

+0

Lo que dijo John. El StackTrace y la InnerException son especialmente útiles. – MetalMikester

0

Con Silverlight 3, el depurador de Visual Studio atrapa estas excepciones para que el gestor de excepciones - no se alcanza nunca - confusamente.Sin embargo, cuando se ejecuta sin el depurador, el controlador de excepción se llama como se esperaba. Supongo que esto está bien siempre y cuando uno esté al tanto. Admito que desperdicié unas horas tratando de descubrir cómo profundizar en el funcionamiento interno de Silverlight/Wcf/Browser para obtener mi excepción. No vayas allí.

0

El uso de un generador de proxy WCF personalizado es una buena solución para manejar excepciones asincrónicas en Silver-light. Haga clic en here para descargar el código fuente.

0

Con XNA en WP7, descubrí que no tenía más remedio que agregar manualmente try/catch a los diversos métodos async End * FunctionName *(); nada más lo intenté evitaría la falla de la aplicación & apagado cuando el servidor no estaba disponible. Es un verdadero lastre tener que actualizar manualmente este código cuando cambia un servicio.

Me sorprende que este no sea un problema mayor ya que no parece haber otra forma de detectar estas excepciones en WP7 usando XNA, pero supongo que esto solo dice más sobre cuántas (== no muchas) personas están tratando de hacer esto más que cualquier otra cosa. Si simplemente hicieran que slsvcutil.exe generase métodos de sincronización, podríamos detectarlos fácilmente dentro de nuestro propio hilo de trabajo, pero desafortunadamente el código generado utiliza subprocesos de grupo de subprocesos sin medios para detectar las excepciones.

0

Para manejar esta situación, use la TargetInvocationException. Esto capturará la excepción cuando la red no funcione o su servicio no esté disponible.

Cuestiones relacionadas