Jestem zaskoczony. Być może ktoś może rzucić trochę światła na zachowanie klienta WCF, którego obserwuję.Korzystanie z WCF, zamykanie i rozszerzenia
Korzystając z próbek WCF, zacząłem grać z różnymi podejściami do komunikacji klient/serwer WCF. Podczas wykonywania 1M żądania testowego równolegle, używałem SysInternals TcpView do monitorowania otwartych portów. Teraz, istnieją co najmniej 4 różne sposoby, aby zadzwonić do klienta:
- utworzyć klienta, rób swoje i niech GC zbierać to
- Tworzenie klienta w wykorzystaniem bloku, niż rób swoje
- Tworzenie kanału klienta z wykorzystaniem fabrycznie w bloku, nie rób swoje
- Tworzenie klienta lub kanału, ale używać WCF Extensions robić swoje rzeczy
teraz, o ile mi wiadomo, tylko opcje 2-4, jawnie zadzwoń client.Close(). Podczas ich wykonywania widzę wiele portów pozostawionych w stanie TIME_WAIT. Spodziewałbym się, że opcja 1 będzie najgorszym scenariuszem, z powodu polegania na GC. Jednak, ku mojemu zaskoczeniu, wydaje się być najczystszym z nich wszystkich, co oznacza, że nie pozostawia żadnych długich portów.
Czego mi brakuje?
UPDATE: kod
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);
});
}
Brakuje jakiegoś kodu źródłowego ... Czy możemy zobaczyć twoje testy jednostkowe? –
Zobacz http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-wcf-client-using-block-issue - użycie bloku może spowodować problemy z WCF. – TrueWill
Dzięki za link, dość ciekawa lektura, ale nadal nie wyjaśnia, dlaczego GC nie pozostawia TIME_WAIT z tyłu, ale client.Close() robi. – Darek