c# wcf exception-handling channel faulted

c# - Manejar el cliente WCF persistente que entra en estado de falla



exception-handling channel (2)

Tenemos un servicio WCF que estamos consumiendo desde una aplicación web. El cliente que estamos usando se generó usando la opción "Agregar referencia de servicio" de Visual Studio. Dado que es una aplicación web, y dado que es probable que la naturaleza de la aplicación conduzca a sesiones relativamente cortas, optamos por crear una instancia del cliente cuando un usuario inicia sesión y la mantiene durante toda la sesión. manejar la eliminación de él cuando la sesión es a través.

Esto me lleva a mi pregunta: estamos tratando de decidir la mejor manera de manejar el canal del cliente entrando en un estado de falla. Después de buscar alrededor de algunos, hemos llegado a esto:

if(client.State = CommuncationState.Faulted) { client = new Client(); } try { client.SomeMethod(); } catch //specific exceptions left out for brevity { //logging or whatever we decide to do throw; }

Sin embargo, esto no funciona debido al hecho de que, al menos en nuestro caso, incluso si el servicio está inactivo, el cliente mostrará el estado Open hasta que realmente intente hacer una llamada usándolo, en cuyo momento entra en el Estado Faulted .

Así que esto nos deja a hacer otra cosa. Otra opción que se nos ocurrió fue:

try { client.SomeMethod(); } catch { if(client.State == CommunicationState.Faulted) { //we know we''re faulted, try it again client = new Client(); try { client.SomeMethod(); } catch { throw; } } //handle other exceptions }

Pero eso huele. Obviamente, podríamos evitar esto utilizando un nuevo cliente y eliminándolo para cada llamada. Eso parece innecesario, pero si es de la manera correcta, entonces supongo que eso es lo que optaremos. Entonces, ¿cuál es la mejor manera de manejar con gracia la determinación de si el cliente está en un estado defectuoso y luego hacer algo al respecto? ¿Deberíamos realmente conseguir un nuevo cliente para cada llamada?

Otra cosa a tener en cuenta: la creación de instancias del cliente y toda esta verificación y manejo se realiza en una clase de envoltorio para el cliente. Si lo hacemos de la manera que pretendemos, es transparente para la aplicación en sí, ya que hacer llamadas y manejar las excepciones no requiere un código especial.


Intente manejar el evento .Faulted en el proxy del cliente, por ejemplo:

((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted); private void client_Faulted(object sender, EventArgs e) { client = new Client(); ((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted); }

Debería activar el instante en que el canal falla, dándole la oportunidad de volver a abrirlo.

También debe ajustar cada llamada a un método client en un bloque try-catch, y quizás incluso envolver eso en un bucle while() que reintenta la llamada n veces y luego registra una falla. P.EJ:

bool succeeded = false; int triesLeft = 3; while (!succeeded && triesLeft > 0) { triesLeft--; try { client.SomeMethod(); succeeded = true; } catch (exception ex) { logger.Warn("Client call failed, retries left: " + triesLeft; } } if (!succeeded) logger.Error("Could not call web service");

En mi código he llegado a usar ManualResetEvent para bloquear el ciclo while () hasta que el controlador de eventos client_Faulted haya tenido la oportunidad de volver a crear el proxy del client .


Para responder a su pregunta, puede manejar el evento con fallas de la propiedad ChannelFactory de la siguiente manera:

client.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);

Eso debería permitirle realizar cualquier registro / limpieza que necesite hacer.

Como recomendación general, no debe dejar el canal abierto mientras dure la sesión, así que asegúrese de estar cerrando el canal correctamente (anulando la excepción) una vez que haya finalizado.

Además, si es posible, considere NO usar la Referencia del Servicio Agregar de Visual Studio, o al menos limpiar el código / configuración que genera. Recomiendo que si desea usar una implementación proxy, cree la suya propia derivando de ClientBase , o use una implementación ChannelFactory . Como menciona una clase de envoltorio, le recomendaría que use un ChannelFactory y maneje el evento Faulted para sus necesidades de limpieza.