2009-05-01 8 views
9

Uso WCF para un sistema de servidor de cliente. Cuando agrego una referencia de servicio a IService en el servidor, se genera una clase proxy ServiceClient. Mi código es el siguiente:Reutilizar una clase de cliente en WCF después de su falla

ServiceClient client = new ServiceClient(); 
try 
{ 
    client.Operation1(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 
try 
{ 
    client.Operation2(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 

El problema es que si hay una excepción comunicación en la primera convocatoria, los cambios de estado del cliente en fallo, y no sé cómo volver a abrirlo para que el segunda llamada. ¿Hay alguna manera de volver a abrirlo? o debería crear uno nuevo y reemplazar la instancia (¿No parece una manera elegante)?

Respuesta

0

Esto es muy probablemente causado por una excepción no controlada en el lado del servidor. El tiempo de ejecución de WCF termina de forma predeterminada su instancia de servicio y pone el canal en estado de error en caso de excepción no controlada y ya no puede comunicarse por ese canal. Por lo tanto, deberá establecer una nueva sesión con el servicio. Debería capturar excepciones en el lado del servidor y enviar las fallas de jabón levantando FaultException o definiendo FaultContract. También hay un comportamiento del servicio returnUnknownExceptionsAsFaults que puede usar.

16

Una vez que un objeto ICommunicationObject (su objeto cliente WCF) está en estado de error, la única manera de "volver a abrirlo" es crear uno nuevo.

ServiceClient client = new ServiceClient(); 
try 
{ 
    client.Operation1(); 
} 
catch(Exception ex) 
{ 
    if (client.State == CommunicationState.Faulted) 
    { 
      client.Abort(); 
      client = new ServiceClient(); 
    } 
} 
try 
{ 
    client.Operation2(); 
} 
catch(Exception ex) 
{ 
    // Handle Exception 
} 
+0

El problema es que tenemos una función interna que obtiene un delegado a una función en un servidor proxy de servicio, y ejecuta la función repetidamente hasta que no se lanza ninguna excepción de comunicación (nuestra implementación a la reconexión automática). Entonces en esta solución, la función creará una instancia del proxy para cada intento de ejecución, y tendrá que devolver una instancia actualizada a la persona que llama, por lo que no tendrá un proxy cerrado ... Algo feo: -/ – Andy

5

Si hay una excepción de la comunicación en la primera llamada que está provocando un estado de fallo, hay que básicamente "recrear" el proxy de cliente WCF. En el ejemplo que probablemente hacer algo como:

if (client.State == CommunicationState.Faulted) 
    client = new ServiceClient(); 

Esto le permitiría "volver a abrir" la conexión si tiene un fallo. Puede parecer un poco exagerado, pero si usted está recibiendo una excepción de la comunicación en el lado del cliente, es probable que haya algo más en juego (es decir:?? Servidor muertos servidor no responde)

Buena suerte

3

acuerdo con las últimas respuestas, una vez que fallaste, debes abortar. Utilizamos una combinación de lambdas y un método como el siguiente para hacer esto:

public static void Use<TServiceInterface>(TServiceInterface proxy, Action handler) 
    { 
    Type proxyType = typeof(TServiceInterface); 
    IClientChannel channel = (IClientChannel)proxy; 

    try 
    { 
     handler(); 

     _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name)); 

     channel.Close(); 

     _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name)); 
    } 
    catch 
    { 
     if (channel.State == CommunicationState.Faulted) 
     { 
      _logSource.Log(LogLevel.Debug, string.Format("Aborting client channel for '{0}' ...", proxyType.Name)); 

      channel.Abort(); 

      _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' aborted.", proxyType.Name)); 
     } 
     else 
     { 
      _logSource.Log(LogLevel.Debug, string.Format("Closing client channel for '{0}' ...", proxyType.Name)); 

      channel.Close(); 

      _logSource.Log(LogLevel.Debug, string.Format("Client channel for '{0}' closed.", proxyType.Name)); 
     } 

     throw; 
    } 
    } 

Esta es una ligera modificación de una solución que ya está en la net, pero funciona muy bien para el manejo de los proxies. Luego puede poner múltiples llamadas de servicio en la misma expresión lambda y pasarlo al método.

+1

En la solución que proporcionó, siempre cierra el canal después del primer uso, y puede dar como resultado un mal rendimiento o incluso una funcionalidad incorrecta cuando se usa la sesión. También es extraño que una función que no crea el canal, lo está cerrando – Andy

+0

El método anterior actúa como una instrucción using en C#. Tiene razón en que llama cerca después de que se ejecuta la acción del controlador, pero creo que lo que se está perdiendo es que puede haber un número infinito de instrucciones en la acción del controlador. Puede hacer 15 llamadas a la interfaz de servicio si lo desea. Además, no creo que sea extraño que la función no lo haga todo. Es bastante común separar la construcción y la destrucción de un objeto en un método separado o segmentos de código separados. Las fábricas no suelen asumir la responsabilidad de limpiar los objetos que crean –

Cuestiones relacionadas