2015-07-27 13 views
7

Gli sviluppatori amano scrivere il più breve e semplice codice possibile. Stiamo invocando i servizi WCF in C# e ci chiediamo se la seguente intuizione sia giusta o sbagliata. Un modo di usare ChannelFactory codice è:Quanto è importante chiamare lo smaltimento su WCF ChannelFactory <T> e l'oggetto canale T subito dopo l'uso?

var factory = new ChannelFactory<IService>("Endpoint"); 
var client = factory.CreateChannel(); 

client.DoSomething(); 

((IClientChannel)client).Close(); 
factory.Close(); 

Altre vie (un po 'più pulito) utilizza un oggetto involucro (per la fabbrica e canale) che implementa IDisposable cui dispone sia e utilizzato con blocco:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) { 
    svcWrapper.Channel.DoSomething(); 
} 

Qui, dover chiamare la proprietà del wrapper potrebbe essere un po 'fastidioso per gli sviluppatori. In pratica potrebbe anche essere:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) { 
    IService client = svcWrapper.Channel; 
    client.DoSomething(); 
} 

(Ho anche scoperto this MSDN article dicendo che il blocco utilizzando può nascondere eccezioni)

ciò che gli sviluppatori potrebbero preferire è:

IService client = new ServiceWrapper<IService>("Endpoint").Channel; 
client.DoSomething(); 

Dal libro C# 5.0 in a poche parole:

Un modello comune prevede che la chiamata del finalizzatore venga eliminata. Questo rende la sensazione di quando la pulizia non è urgente e affrettarla chiamando Dispose è più di una ottimizzazione che di una necessità.

Se posso aggiungere questo al mio ServiceWrapper (C# Finalizza/pattern Dispose):

public void Dispose() { 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

~ServiceWrapper() { 
    Dispose(false); 
} 

Poi GC finirà per chiamare Dispose e fare le cose che devono essere fatte. cioè .:

public void Dispose(bool disposing) { 
    if (disposing) { 
     if (_channel != null) { 
      ((IClientChannel)_channel).Close(); 
     } 
     if (_factory != null) { 
      _factory.Close(); 
     } 

     _channel = null; 
     _factory = null; 
    } 
} 

ho la sensazione che questa non è una buona pratica da usare con WCF ChannelFactory<T> e T canale, ma non ho una buona spiegazione che spaventare gli sviluppatori di distanza sotto forma di utilizzarlo. Ragazzi, potete spiegare pls?

Non posso dire che non funziona, l'ho provato e funziona perfettamente. Non riesco a vedere alcuna differenza prestazionale evidente o simile ... Non posso dare altra spiegazione di "Non sai quando viene chiamato il finalizzatore." Grazie!

risposta

5

Bene, l'unica cosa che fa il metodo Dispose è chiudere esplicitamente la connessione. Questo è tutto. Puoi vedere tu stesso nello reference source. Inoltre, ClientBase<T>, la classe base per la connessione fa lo stesso.

Detto questo, se si chiama Close da soli non c'è una reale necessità in questo momento di chiamare Dispose a tutti, anche se direi che realmente dovrebbe Dispose, solo per essere a prova di futuro. Anche questo può essere un fail-safe per gli errori che possono impedire di chiamare Close.

+0

Grazie! Questo cancella un po 'di nebbia. C'è un grosso pericolo nel non chiamare manualmente il 'Close' e ​​lasciare che il finalizzatore lo faccia? – DDan

+0

Oltre a mantenere attive le connessioni che dovrebbero essere chiuse e rovinare la memoria su server e client? No. Questa è una buona ragione per chiuderla il prima possibile però. –

+1

Vedo. Con tutti i mezzi usare il metodo 'Dispose' (per chiamata o per il blocco 'using') sarebbe il modo più sicuro. Grazie per l'aiuto! Qualsiasi chiarimento è ancora benvenuto. – DDan