2009-11-10 10 views
6

Estoy encontrando respuestas mixtas a mi pregunta en la web. Para profundizar en la pregunta:¿Cuál es el ciclo de vida adecuado de un proxy de cliente de servicio WCF en Silverlight 3?

  1. ¿Debería instanciar un cliente de servicio proxy una vez por invocación asincrónica, o una vez por cada aplicación Silverlight?
  2. ¿Debo cerrar el proxy del cliente del servicio explícitamente (como hago en mi aplicación ASP.NET MVC llamando a los servicios de WCF de forma síncrona)?

He encontrado muchos bloggers y carteles de foros que se contradicen entre sí. ¿Alguien puede señalar alguna fuente definitiva o evidencia para responder esto de una vez por todas?

+0

La respuesta probablemente dependa de su servicio. Crear el proxy es costoso, pero hacer un seguimiento de ese único proxy y administrar cualquier error puede ser difícil. – Bryant

Respuesta

0

Debe abrir su cliente por llamada y cerrarlo inmediatamente después. Si tiene dudas busque usando IE en un archivo SVC y mire el ejemplo que tienen allí.

+0

¿Qué significa "inmediatamente después" en el mundo de las llamadas WCF asincrónicas utilizadas en Silverlight? Ciérrelo después de que inicie la llamada asíncrona o ciérrela cuando esté completa. Si esto último, plantea la pregunta de qué pasa si nunca se completa. – Trinition

3

He estado usando Silverlight con WCF desde V2 (trabajando ahora con V4), y esto es lo que he encontrado. En general, funciona muy bien abrir un cliente y simplemente usar ese único cliente para todas las comunicaciones. Y si no está utilizando DuplexHttBinding, también funciona bien hacer exactamente lo contrario, abrir una nueva conexión cada vez y luego cerrarla cuando haya terminado. Y debido a la forma en que Microsoft ha diseñado el cliente WCF en Silverlight, no verá mucha diferencia en el rendimiento entre mantener un cliente abierto todo el tiempo o crear un nuevo cliente con cada solicitud. (Pero si está creando un nuevo cliente con cada solicitud, asegúrese de cerrarlo también).

Ahora, si está utilizando DuplexHttBinding, es decir, si desea llamar a métodos en el cliente del servidor, por supuesto es importante que no cierre el cliente con cada solicitud. Eso es solo sentido común. Sin embargo, lo que ninguna documentación le dice, pero que he encontrado que es absolutamente crítico, es que si está utilizando DuplexHttBinding, solo debe tener una instancia del cliente abierta a la vez. De lo contrario, te encontrarás con todo tipo de desagradables problemas de tiempo de espera que serán realmente difíciles de solucionar. Tu vida será dramáticamente más fácil si solo tienes una conexión.

La forma en que he aplicado esto en mi propio código es ejecutar todas mis conexiones a través de una única clase DataConnectionManager estática que arroja un Assert si intento abrir una segunda conexión antes de cerrar la primera. Unos fragmentos de esa clase:

private static int clientsOpen; 
    public static int ClientsOpen 
    { 
     get 
     { 
      return clientsOpen; 
     } 
     set 
     { 
      clientsOpen = value; 
      Debug.Assert(clientsOpen <= 1, "Bad things seem to happen when there's more than one open client."); 
     } 
    } 

    public static RoomServiceClient GetRoomServiceClient() 
    { 
     ClientsCreated++; 
     ClientsOpen++; 
     Logger.LogDebugMessage("Clients created: {0}; Clients open: {1}", ClientsCreated, ClientsOpen); 
     return new RoomServiceClient(GetDuplexHttpBinding(), GetDuplexHttpEndpoint()); 
    } 

    public static void TryClientClose(RoomServiceClient client, bool waitForPendingCalls, Action<Exception> callback) 
    { 
     if (client != null && client.State != CommunicationState.Closed) 
     { 
      client.CloseCompleted += (sender, e) => 
      { 
       ClientsClosed++; 
       ClientsOpen--; 
       Logger.LogDebugMessage("Clients closed: {0}; Clients open: {1}", ClientsClosed, ClientsOpen); 
       if (e.Error != null) 
       { 
        Logger.LogDebugMessage(e.Error.Message); 
        client.Abort(); 
       } 
       closingIntentionally = false; 
       if (callback != null) 
       { 
        callback(e.Error); 
       } 
      }; 
      closingIntentionally = true; 
      if (waitForPendingCalls) 
      { 
       WaitForPendingCalls(() => client.CloseAsync()); 
      } 
      else 
      { 
       client.CloseAsync(); 
      } 
     } 
     else 
     { 
      if (callback != null) 
      { 
       callback(null); 
      } 
     } 
    } 

La parte molesta, por supuesto, es si sólo tiene una conexión, es necesario trampa para que cuando se cierra la conexión sin querer y tratar de volver a abrirlo. Y luego necesita reinicializar todas las devoluciones de llamadas para las que se registraron sus diferentes clases. En realidad no es tan difícil, pero es molesto asegurarse de que se haga bien. Y, por supuesto, las pruebas automatizadas de esa parte son difíciles, si no imposibles. . .

0

WCF tienen configuraciones que le dicen cuánto tiempo debe esperar para que una llamada regrese, mi idea es que cuando no termine en el tiempo permitido, AsyncClose lo cerrará. Por lo tanto, llame al cliente.AsyncClose().

Cuestiones relacionadas