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. . .
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