2009-11-10 13 views
6

Sto trovando risposte miste alla mia domanda sul web. Per elaborare la domanda:Qual è il ciclo di vita corretto di un proxy client del servizio WCF in Silverlight 3?

  1. Devo istanziare un proxy client di servizio una volta per chiamata asincrona o una volta per l'app Silverlight?
  2. Devo chiudere esplicitamente il proxy del client di servizio (come faccio nella mia applicazione ASP.NET MVC che chiama i servizi WCF in modo sincrono)?

Ho trovato molti blogger e poster di forum che si contraddicono a vicenda. Qualcuno può indicare fonti o prove definitive per rispondere una volta per tutte a questa domanda?

+0

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

risposta

0

È necessario aprire il client per chiamata e chiuderlo subito dopo. In caso di dubbio, navigare usando IE in un file SVC e guardare l'esempio che hanno lì.

+0

Cosa significa "immediatamente dopo", tuttavia, nel mondo delle chiamate WCF asincrone utilizzate in Silverlight? Chiuderlo dopo aver avviato la chiamata asincrona o chiuderlo una volta completato? Se quest'ultimo, si pone la domanda di cosa succede se non è mai completato. – Trinition

3

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

0

WCF ha impostazioni di configurazione che indicano quanto tempo deve attendere il ritorno di una chiamata, il mio pensiero è che quando non si completa nel tempo consentito, AsyncClose lo chiude. Pertanto chiama client.AsyncClose().

Problemi correlati