私は困惑しています。おそらく、私が観察しているWCFクライアントの動作に誰かが光を当てることができます。
WCF サンプルを使用して、WCF クライアント/サーバー通信へのさまざまなアプローチを試してみました。1M のテスト リクエストを並行して実行している間、SysInternals TcpView を使用して開いているポートを監視していました。現在、クライアントを呼び出す方法は少なくとも 4 つあります。
- クライアントを作成し、必要なことを行い、GC に収集させます
- あなたのことをするよりも、usingブロックでクライアントを作成してください
- あなたのことをするよりも、usingブロックのファクトリからクライアントチャネルを作成します
- クライアントまたはチャネルを作成しますが、WCF 拡張機能を使用して自分のことを行います
現在、私の知る限り、オプション 2 ~ 4 のみが明示的に client.Close() を呼び出します。それらの実行中に、多くのポートが TIME_WAIT 状態のままになっていることがわかります。GC に依存しているため、オプション 1 が最悪のシナリオになると思います。しかし、驚いたことに、それらすべての中で最もクリーンであるように見えます。つまり、残存するポートを残しません。
私は何が欠けていますか?
更新: ソース コード
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);
});
}