actualización
Es cierto que esto es un poco de código mundano a escribir. I currently prefer this linked answer, y no ve ningún "hackeo" en ese código que pueda causar problemas en el futuro.
Ésta es la manera recomendada por Microsoft para manejar cliente WCF llama:
Para más detalles ver: Expected Exceptions
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
Información adicional Así que muchas personas parecen estar haciendo esta pregunta en WCF que Microsoft incluso creó una muestra dedicada para demostrar cómo manejar excepciones:
c: \ WF_WCF_Samples \ WCF \ Básico \ Client \ ExpectedExceptions \ CS \ cliente
Descargar la muestra: C# o VB
Teniendo en cuenta que hay tantos problemas involving the using statement, (heated?) Internal discussions y threads sobre este tema, No voy a perder el tiempo tratando de convertirme en un código vaquero y encontrar una manera más limpia. Simplemente lo absorberé, e implementaré los clientes de WCF de esta forma detallada (aunque de confianza) para mis aplicaciones de servidor.
fallas adicionales opcionales para ponerse
Muchas excepciones derivan de CommunicationException
y no creo que la mayoría de esas excepciones se debe reintentar. Recorrí cada excepción en MSDN y encontré una breve lista de excepciones reintentables (además de TimeOutException
arriba). Avíseme si me perdí una excepción que debería volver a intentarse.
Exception mostRecentEx = null;
for(int i=0; i<5; i++) // Attempt a maximum of 5 times
{
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
mostRecentEx = cte;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
mostRecentEx = enfe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
mostRecentEx = stbe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
catch(Exception ex)
{
throw ex; // rethrow any other exception not defined here
}
}
if (mostRecentEx != null)
{
throw new Exception("WCF call failed after 5 retries.", mostRecentEx);
}
Sobre la base de los eslabones de esa pregunta seguro que me parece que las cosas WCF no debería haber implementado IDisposable, sino que debería haber tenido una arquitectura completamente diferente para la limpieza. – NotMe
@Chris Lively De hecho, parece que todo el mundo está tratando de hackear una declaración 'using' que va en contra de las recomendaciones de Microsoft. Las discusiones internas privadas de MSFT aparentemente quieren que las aplicaciones de producción tengan un manejo específico de excepciones estructuradas. Será detallado y molesto, pero supongamos que necesito absorberlo. – LamonteCristo
No puedo encontrar el enlace en este momento pero vi un sitio donde alguien había usado lambdas para enmascarar este comportamiento de una manera bastante interesante. Hizo que el código fuera mucho más fácil de usar. Si vuelvo a encontrarlo, publicaré el enlace. – Avilo