2011-02-19 12 views
5

Hay varias preguntas sobre stackoverflow sobre las conexiones de WCF de cierre, sin embargo las más altas respuestas de clasificación se refiere a este blog:Excepción en la declaración "using" con WCF no cerrando las conexiones correctamente. ¿Cómo se cierran las conexiones de los clientes de WCF o las que tienen excepciones?

http://marcgravell.blogspot.com/2008/11/dontdontuse-using.html

Tengo un problema con esta técnica cuando me puse un punto de interrupción en el servidor y dejar que el cliente cuelgue por más de un minuto. (Estoy creando intencionalmente una excepción de tiempo de espera)

El problema es que el cliente parece "bloquearse" hasta que el servidor finaliza el proceso. Mi suposición es que todo se está limpiando después de la excepción.

En lo que se refiere a la TimeOutException parece que la lógica retry() del cliente continuará a volver a enviar la consulta al servidor una y otra vez, donde puedo ver la cola depurador del lado del servidor hasta las solicitudes y luego ejecutar cada solicitud en cola concurrentemente. Mi código no espera que WCF actúe de esta manera y puede ser la causa de los problemas de corrupción de datos que estoy viendo.

Algo no cuadra totalmente con esta solución.

¿Cuál es la forma moderna que todo lo abarca de hacer frente a los fallos y excepciones en un proxy WCF?

Respuesta

7

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); 
} 
3

Closing and Disposing a WCF Service

Como ese puesto alude a, que se cierran cuando no había excepciones y Abortar cuando hay errores. Dispose y por lo tanto Using no se debe utilizar con WCF.

+1

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

+0

@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

+0

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

Cuestiones relacionadas