ChannelFactory.Close VS IClientChannel.Close
Asked Answered
R

4

34

Consider the following code which is typcial of many ChannelFactory examples:

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();

Note that when proxy.Open() is called, both the the channel's state and the ChannelFactory's state become "Opened". When proxy.Close() is called, the channel's state becomes "closed", but the ChannelFactory's state remains "Opened".

Should one be closing the ChannelFactory as well? I don't seem to see this in many examples. Also, if possible please explain the difference between having a channel open vs having a channel factory open.

Additionally, I am aware of the IDisposable issue, so it probably can be ignored for the sake of this question unless it has direct impact on the answer.

Referendum answered 14/5, 2009 at 22:59 Comment(1)
Instead of IClientChannel.Close, I think you meant ICommunicationObject.CloseGloriole
U
14

As you know, the ChannelFactory creates the client channel based on configuration. You may want to create multiple client channels from an existing factory (to the same endpoint as that is locked). If you're done using the factory to create channels, there is no reason not to close it.

But, why might you want to keep it open? Here's an interesting article on WCF clients that says:

Checking the value of the System.ServiceModel.ICommunicationObject.State property is a race condition and is not recommended to determine whether to reuse or close a channel.

Rather than reuse a channel, you might want to simply create a new one with the channel factory. More on the client architecture is here.

Unintentional answered 14/5, 2009 at 23:21 Comment(1)
I found your answer inaccurate when you say If you're done using the factory to create channels, there is no reason not to close it. It will fail if you do - see my response.Gare
G
21

I found the main answer inaccurate so I am responding here.

Obviously Microsoft has made an absolute mess out of Channles and Factories and Clients. Documentation is not also helpful since they seem to be there just to cover up the mess so I had to resort to testing.

With the performance issues regarding non-cached Channels, implementation changed in v3.5 to address these and added caching but that only complicated the issue.

The point is channel in ChannelFactory is in fact not different from the channel used by IClientChannel when you create a channel using ChannelFactory.CreateChannel(). It is all the same pot. Believe me not? Try:

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

So really, internally it is all the same channel. I personally have started disposing the channel factories and not client channels and have not encountered any issue. I have also tried doing this in a loop with creation of 100000 client channels, and only closing ChannelFactory.

Gare answered 15/2, 2011 at 17:14 Comment(10)
But can you reuse the factory after closing it? I thought there was a performance hit in creating the factory for each channel.Ait
Why I'm asking is because I wrote this generic wrapper: blog.tomasjansson.com/2010/12/disposible-wcf-client-wrapperAit
Closed channel factory cannot be reused. Creating new channel factory affects the performance, but if you like me have to use authentication, once you opened it, then you cannot change the username/password so you have to create it everytime.Gare
But it doesn't affect the performance that much to create a new channel factory: blogs.msdn.com/b/wenlong/archive/2007/10/27/…. According to that page the channel factory itself is doing some caching to improve performance.Ait
Interanlly, it is not the same channel; ChannelFactory.Close loops through its channels and closes them manually. THATS why you get the disposed exception.Combative
@MichaelEdenfield Thanks Michael. Your observation is valuable.Gare
If I just want to use that ONE channel, I am supposed to keep the factory open as long as I need the channel? That seems a bit counter-intuitive...Acuna
@JoãoPortela Tell me about it! Yes, it is. As I explained, closing factory will close underlying channel and clients.Gare
Notice that the Close method on a ChannelFactory is in fact an equivalent of Dispose(). Check the Framework Design Guidelines, where it is stated that in special cases a Close() is more preferred than Dispose(), for example the StreamWrite has this also...Hereinbefore
Closing the channel factory solved an issue for me with bound ephemeral TCP ports in a WCF facade. Odd.Ingrained
U
14

As you know, the ChannelFactory creates the client channel based on configuration. You may want to create multiple client channels from an existing factory (to the same endpoint as that is locked). If you're done using the factory to create channels, there is no reason not to close it.

But, why might you want to keep it open? Here's an interesting article on WCF clients that says:

Checking the value of the System.ServiceModel.ICommunicationObject.State property is a race condition and is not recommended to determine whether to reuse or close a channel.

Rather than reuse a channel, you might want to simply create a new one with the channel factory. More on the client architecture is here.

Unintentional answered 14/5, 2009 at 23:21 Comment(1)
I found your answer inaccurate when you say If you're done using the factory to create channels, there is no reason not to close it. It will fail if you do - see my response.Gare
A
4

Another option is to use the static CreateChannel method: msdn.microsoft.com/en-us/library/aa344556.aspx

Adelaideadelaja answered 14/9, 2011 at 19:53 Comment(0)
G
2

The answer is already here, but it is spread over several comments and answers and not entirely clear, hence my answer.

Should one close the ChannelFactory as well as the Channel?

No. If you want to create multiple Channels from each ChannelFactory, you should dispose of the ChannelFactory, which will dispose all the Channels it created for you.

If you want to create one channel for each (endpoint, binding) pair, you should use this static function: ChannelFactory<ServiceType>.CreateChannel(binding, endpoint) (which avoids the issue as it does not create a second IDisposable), and you should dispose of the channel it returns.

Disposing of both the channelfactory and any of the channels it created will raise an ObjectDisposed exception.

Gloriole answered 25/10, 2018 at 8:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.