web-dev-qa-db-ja.com

ChannelFactory.Close VS IClientChannel.Close

多くのChannelFactoryの例に典型的な次のコードについて考えてみます。

WSHttpBinding myBinding = new WSHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress(
   ConfigurationSettings.AppSettings["HelloWorldServiceURL"]);  

ChannelFactory<IHelloWorldService> myChannelFactory = 
   new ChannelFactory<IHelloWorldService>(myBinding, myEndpoint);

IHelloWorldService proxy = myChannelFactory.CreateChannel();
((IClientChannel)proxy).Open();
HelloWorldDataContract dc = proxy.SayHello();
((IClientChannel)proxy).Close();

Proxy.Open()が呼び出されると、チャネルの状態とChannelFactoryの状態の両方が「Opened」になることに注意してください。 proxy.Close()が呼び出されると、チャネルの状態は「クローズ」になりますが、ChannelFactoryの状態は「オープン」のままです。

ChannelFactoryも閉じる必要がありますか?多くの例でこれは見られないようです。また、可能であれば、チャネルを開くこととチャネルファクトリを開くことの違いを説明してください。

さらに、私は IDisposable issue を認識しているので、回答に直接影響しない限り、この質問のためにおそらく無視することができます。

33
Daniel Auger

ご存知のように、ChannelFactoryは構成に基づいてクライアントチャネルを作成します。既存のファクトリから(ロックされているのと同じエンドポイントに)複数のクライアントチャネルを作成することをお勧めします。ファクトリを使用してチャネルを作成し終えた場合、それを閉じない理由はありません。

しかし、なぜあなたはそれを開いたままにしておきたいのですか?ここに興味深い WCFクライアントに関する記事 があります:

System.ServiceModel.ICommunicationObject.Stateプロパティの値を確認することは競合状態であり、チャネルを再利用するか閉じるかを決定することはお勧めしません。

チャネルを再利用するのではなく、チャネルファクトリを使用して新しいチャネルを作成することをお勧めします。 クライアントアーキテクチャの詳細はこちら

14
JP Alioto

主な回答が不正確であることがわかったので、ここで回答します。

明らかに、MicrosoftはChannlesとFactorys and Clientsから絶対的な混乱を作成しました。ドキュメントは混乱を隠すためだけにあるように見えるので、ドキュメントも役に立ちません。そのため、テストに頼らざるを得ませんでした。

キャッシュされていないチャネルに関するパフォーマンスの問題により、実装が v3.5 で変更され、これらに対処してキャッシュが追加されましたが、問題は複雑になりました。

重要なのは、ChannelFactoryのチャネルは、実際には、ChannelFactory.CreateChannel()を使用してチャネルを作成するときにIClientChannelが使用するチャネルと同じです。それはすべて同じポットです。信じられない?試してください:

ChannelFactory<IService> factory = new ChannelFactory<IService>();
// ...
IService service = factory.CreateChannel();
factory.Close();
service.DoIt() // Throws object disposed exception

つまり、実際には、内部的にはすべて同じチャネルです。私は個人的にクライアントチャネルではなくチャネルファクトリの廃棄を開始しましたが、問題は発生していません。また、100000クライアントチャネルを作成し、ChannelFactoryを閉じるだけで、これをループで実行しようとしました。

19
Aliostad

もう1つのオプションは、静的CreateChannelメソッドを使用することです。 msdn.Microsoft.com/en-us/library/aa344556.aspx

4
Cesar Maiorino

答えはすでにここにありますが、それはいくつかのコメントと答えにまたがっており、完全に明確ではないので、私の答えです。

ChannelFactoryとChannelを閉じる必要がありますか?

いいえ。各ChannelFactoryから複数のチャネルを作成する場合は、ChannelFactoryを破棄する必要があります。これにより、作成されたすべてのチャネルが破棄されます。

(エンドポイント、バインディング)ペアごとに1つのチャネルを作成する場合は、 この静的関数ChannelFactory<ServiceType>.CreateChannel(binding, endpoint)を使用する必要があります(2番目のIDisposableを作成しないため、問題を回避できます)、そしてあなたはそれが返すチャンネルを処分するべきです。

Channelfactoryとそれが作成したチャネルの両方を破棄すると、ObjectDisposed例外が発生します。

1
TamaMcGlinn