Sono perplesso. Forse qualcuno può far luce sul comportamento del client WCF che sto osservando.WCF utilizzo, chiusura ed estensioni
Utilizzando gli esempi WCF, ho iniziato a giocare con approcci diversi alla comunicazione client/server WCF. Mentre eseguivo 1M di richieste di test in parallelo, stavo usando SysInternals TcpView per monitorare le porte aperte. Ora, ci sono almeno 4 modi diversi di chiamare il cliente:
- Creare il client, fare la vostra cosa, e lasciare GC ritirarlo
- Creare il cliente in un blocco utilizzando, di fare la tua cosa
- Creare il canale del client dalla fabbrica in un blocco utilizzando, di quanto non facciano la tua cosa
- Creare il client o il canale, ma l'uso WCF Extensions per fare la tua cosa
Ora, a mia conoscenza, solo le opzioni 2-4, chiamare esplicitamente client.Close(). Durante la loro esecuzione vedo molte porte lasciate nello stato TIME_WAIT. Mi aspetto che l'opzione 1 sia la peggiore delle ipotesi, a causa della dipendenza dal GC. Tuttavia, con mia sorpresa, sembra che sia il più pulito di tutti, nel senso che non lascia dietro di sé alcuno sbocco.
Cosa mi manca?
UPDATE: Codice sorgente
private static void RunClientWorse(ConcurrentBag<double> cb)
{
var client = new CalculatorClient();
client.Endpoint.Address = new EndpointAddress("net.tcp://localhost:8000/ServiceModelSamples/service");
RunClientCommon(cb, client);
}
private static void RunClientBetter(ConcurrentBag<double> cb)
{
using (var client = new CalculatorClient())
{
client.Endpoint.Address = new EndpointAddress("net.tcp://localhost:8000/ServiceModelSamples/service");
RunClientCommon(cb, client);
}
}
private static void RunClientBest(ConcurrentBag<double> cb)
{
const string Uri = "net.tcp://localhost:8000/ServiceModelSamples/service";
var address = new EndpointAddress(Uri);
//var binding = new NetTcpBinding("netTcpBinding_ICalculator");
using (var factory = new ChannelFactory<ICalculator>("netTcpBinding_ICalculator",address))
{
ICalculator client = factory.CreateChannel();
((IContextChannel)client).OperationTimeout = TimeSpan.FromSeconds(60);
RunClientCommon(cb, client);
}
}
private static void RunClientBestExt(ConcurrentBag<double> cb)
{
const string Uri = "net.tcp://localhost:8000/ServiceModelSamples/service";
var address = new EndpointAddress(Uri);
//var binding = new NetTcpBinding("netTcpBinding_ICalculator");
new ChannelFactory<ICalculator>("netTcpBinding_ICalculator", address).Using(
factory =>
{
ICalculator client = factory.CreateChannel();
((IContextChannel)client).OperationTimeout = TimeSpan.FromSeconds(60);
RunClientCommon(cb, client);
});
}
Ti manca qualche codice sorgente ... Potremmo vedere i test dell'unità? –
Vedere http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue - il blocco using può causare problemi con WCF. – TrueWill
Grazie per il collegamento, una lettura abbastanza interessante, ma non spiega ancora perché GC non lascia TIME_WAITs indietro, ma client.Close(). – Darek