Utilizzo Silverlight con WCF da V2 (ora funziona con V4), ed ecco cosa ho trovato. In generale, funziona molto bene per aprire un client e utilizzare solo quel client per tutte le comunicazioni. E se non stai usando DuplexHttBinding, funziona anche bene l'opposto, per aprire ogni volta una nuova connessione e poi chiuderla quando hai finito. E a causa del modo in cui Microsoft ha architettato il client WCF in Silverlight, non vedrai molte differenze di prestazioni tra mantenere un client sempre aperto e creare un nuovo client a ogni richiesta. (Ma se stai creando un nuovo cliente ad ogni richiesta, assicurati di averlo chiuso.)
Ora, se stai usando DuplexHttBinding, cioè se vuoi chiamare i metodi sul client dal server, è ovviamente importante non chiudere il client con ogni richiesta. Questo è solo buon senso. Tuttavia, ciò che nessuno della documentazione ti dice, ma che ho trovato assolutamente critico, è che se stai usando DuplexHttBinding, dovresti sempre avere un'istanza del client aperta contemporaneamente. Altrimenti, incontrerai tutti i tipi di brutti problemi di timeout che saranno davvero difficili da risolvere. La tua vita sarà molto più facile se hai solo una connessione.
Il modo in cui ho applicato questo codice nel mio codice è di eseguire tutte le mie connessioni attraverso una singola classe statica DataConnectionManager che genera un'Assert se provo ad aprire una seconda connessione prima di chiudere la prima. Alcuni frammenti di quella classe:
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 fastidiosa, ovviamente, è se si dispone di una sola connessione, è necessario trappola per quando quel collegamento si chiude involontariamente e cercare di riaprirlo. E quindi è necessario reinizializzare tutti i callback che le tue diverse classi sono state registrate per gestire. Non è poi così difficile, ma è fastidioso assicurarsi che sia fatto bene. E, naturalmente, il test automatico di quella parte è difficile se non impossibile. . .
La risposta dipende probabilmente dal servizio. La creazione del proxy è costosa, ma tenere traccia di quel singolo proxy e gestire eventuali errori può essere difficile. – Bryant