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.
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.
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.
Another option is to use the static CreateChannel method:
msdn.microsoft.com/en-us/library/aa344556.aspx
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.
Related
We have a service that makes NetTcp calls to other services on different servers. I'm trying to optimize it by caching the ChannelFactories, and by increasing maxOutboundConnectionsPerEndpoint.
I have been using GOOGLE.COM (great website, by the way. Check it out if you haven't heard of them) to try to understand how the channel caching works, and I don't think I have it correct.
Reusing the channel factory - good idea.
Caching channels myself - bad idea. Wcf already does this, as long as all of your channels are created from the same factory. - is that right? If you create a new factory each time, it's not cached?
// factory initialization
var address = "net.tcp://something:8888/testservices";
var factory = new ChannelFactory<ITestService>("configname", new EndpointAddress(address));
// do stuff
var client = factory.CreateChannel(); // you can also pass an address here. how does that effect channel caching?
So that handles the factory stuff. Now, I want to increase maxOutboundConnectionsPerEndpoint, which is achieved via a custom binding. The thing that's not clear there is the GroupName. I can't specify distinct group names in configuration because I'm looking up the URL at runtime. Thus, all channel factories are going to have the same default group name. Are they going to share the same pool, does each factory have it's own?
In the end, I would like to create the custom binding in configuration, then create/cache multiple channel factories as needed, and use them to establish channels. And, I need to increase the maxOutboundConnectionsPerEndpoint per endpoint. I may be calling the same service on 20 different machines, and I want up to 50 cached channels for each. Does the code above achieve that?
Thank you for your help. If there is a link that covers this, please forward. I haven't been able to find it.
I'm using WCF to create a connection beween a server app and client app.
Because I'm using NetTcpBinding, I want to keep alive the channel created by:
T proxy = ChannelFactory<T>.CreateChannel();
I bring the proxy instance into my app to communicate with server. At some moment, I renew this proxy, with a different factory. But I want to release resources from the first factory, by disposing it. But I don't wan't to manage factories and keep a reference to.
Is there a way with the proxy instance to retrive the channel associate to dispose it ?
Like ...
var commObj = (ICommunicationObject)proxy;
commObj.Factory.Dispose();
Thanks
Unfortunately, it is not possible, because Channels and Factories are not linked. But I think your approach is not correct. You should keep a reference to the factory and create Channel as needed. Re-using Channel can be a problem in some cases. A channel can be faulted, but the inner factory will still be valid. Creating a factory has a real cost, and some .net 3.5 SP1, factories are internally stored in a static cache.
I have both ends of a bi-directional connected Stream, which I want to do some communication over. The underlying implementation behind the stream isn't important, I want to work at the Stream level...
Rather than implement my own communications protocol for the stream, I want to use all of the existing WCF goodness to wrap the existing stream with with a bi-directional (request/response + callback) WCF communications channel.
My question is, how can I go about doing this...?
UPDATE:
I've gone down the path of implementing a custom transport. I've got this working, but I'm still not totally happy with it...
I've implemented an IDuplexSessionChannel to wrap the stream, along with appropriate IChannelFactory and IChannelListener, and a Binding Element for creating the channel factories. Now, I just pass through the connected stream, and eventually pass these into the transport channel when it is created.
So, I can create the client proxy for accessing the service via the stream as follows:
var callback = new MyCallback();
var instanceContext = new InstanceContext( callback );
var pipeFactory = new DuplexChannelFactory<IMyService>( instanceContext, new StreamBinding(clientStream),
new EndpointAddress("stream://localhost/MyService"));
var serviceProxy = pipeFactory.CreateChannel();
The problem I have is, it seems WCF is set on using a ServiceHost to create the server end of the channel, via a IChannelListener. In my case, I already have a connected stream, and I won't be able to listen for any more incoming connections. I can work around this, but I'd much rather not use a ServiceHost to create the server end of the channel, because I end up with a lot of obscure boilerplate and hacks to make it work.
Questions
I'm looking, therefore, for a better way to take the IDuplexSessionChannels, and wrap these into a Channel proxy at both the server and client ends.
Or maybe a different ServiceHost implementation that doesn't require a IChannelListener.
Really, the problem here is I don't want a single server, multiple client arrangement, I have a 1-1 relationship between my WCF Service and the client. Is there a correct way to instantiate one of these?
To put it yet another way, I want to create the Server-side service instance without using a ServiceHost.
Any suggestions would be appreciated at this stage.
Use a client at both ends. You will need to define your contracts carefully though. If you have ClientA and ClientB at either end of the stream, when ClientA sends a request, ClientB will expect it to look like what it sees as it's defined callback contract and vice versa.
I am currently looking at some code which basically reads data line-by-line from a file and calls an appropriate method on a WCF client for each line. My problem with the code is that a new client is created for each operation ie:
function CallSomeOp(line)
{
using (var client = new Client()
{
client.SomeOp(line);
}
}
This seems to make the client close the connection and reopen a new one for each line in the file which seems like a big overhead. What I would like to do is move the creation of the client outside the function and into initialization, so that multiple operations are called on one client, ie:
using (var client = new Client())
{
for(var line in lines)
{
CallSomeOp(line, client);
}
}
But I'm not sure if this is OK or not. Is there some problem with calling multiple operations on a client, ie will I eventually run out of memory or something?
An operation is typically stateless, so that's expected behaviour. You can change the InstanceContextMode though. This determines if a new instance is created with each call or that there is a single instance. The question is, should you? Like I said, a single call is typically stateless. Having just a single instance doesn't scale very well either. I'd suggest to keep InstanceContextMode to be PerCall, that way, for every call the webserver creates a single instance, I wouldn't worry too much about overhead. If overhead really does become a problem, maybe a service isn't what you need.
Then there's the ConcurrencyMode which allows you to specify multiple threads to be created.
As far as the client is concerned, you don't need to re-create it everytime you want to call an operation. Alternatively, you could also look at the ChannelFactory if both client and server have knowledge of the contract. This answer provides some detail.
It's definitely a good idea to reuse a WCF client across multiple calls, since there is indeed a cost in creating new instances of it, even if that's been improved in later versions.
The most important thing to be aware of when reusing a WCF client, though, is that if a service operation fails, the whole client will be put in a faulted state and can no longer be used.
You will have to take this into consideration in your client code. Depending on your requirements, one way to handle this situation could be to recreate the client proxy in case of failure and continue processing the input, like shown in this example:
var client = new ServiceClient();
foreach (var line in lines)
{
try
{
client.DoSomething(line);
}
catch
{
client.Abort();
client = new ServiceClient()
}
}
Note that you may also want to keep track of how many times the service call fails and with what type of exception, since in some situations it would make more sense to completely abort the operation instead of keep trying, e.g. when the remote service is not reachable.
As the title implies I am trying to get an understanding of why in WCF sometimes people choose to "generate proxies" vs using a ChannelFactory to manually create new channel instances. I have seen examples of each, but haven't really found any explanations of WHY you would go for one vs the other.
To be honest I have only ever worked with channels and the ChannelFactory<T> from code I have inherited, ie:
IChannelFactory<IDuplexSessionChannel> channelFactory =
binding.BuildChannelFactory<IDuplexSessionChannel>();
_duplexSessionChannel = channelFactory.CreateChannel(endpointAddress);
So why would I "generate a proxy"? What are the benefits and drawbacks?
The main difference is this:
generating a proxy only requires you to know the URL where the service resides. By generating the proxy, everything else (the service contract and the data contracts involved) will be determined by inspecting the metadata of the service
in order to directly create a ChannelFactory<T>, you must have direct access to the assembly that contains that service contract T for which you're generating a channel factory. This only ever works if you basically control both ends of the channel and you can share the assembly that contains those service contracts. Typically, with a third-party service, this won't be the case - with your own services, yes.
The second important point is this:
creating a generated proxy basically does the two steps that you would do - create a ChannelFactory<T>, and from that, create the actual channel - in a single constructor. You have no control over these two steps.
doing your own Channel creation is beneficial, since the creation of the ChannelFactory<T> is the expensive step - so yo could cache your channel factory instance somewhere. Creating and re-creating the actual channel from the factory is much less involved step which you can do more frequently
So if you do control both ends of the communication, service and client, you do have the option to share the service contracts in a separate assembly, and thus you have more options.
With most third-party services, you just simply don't have that option.
Using a proxy is simpler and easier to understand. You get to deal in terms of simple things - classes and methods on those classes - instead of complex, network-related things like channels.
OTOH, this is not made easier by the design flaw in WCF that prevents the same simple use of a WCF proxy that we could do with ASMX proxies:
using (var client = new MyServiceClient())
{
}
If you use this pattern with WCF, you can lose the original exception when the block is exited due to an exception. client.Dispose() can throw an exception, which will overwrite the exception originally being thrown. A more complex pattern is required.
This may help you:
When to use a proxy?
If you have a service that you know is going to be used by several applications or is generic enough to be used in several places, you’ll want to use the proxy classes.
When to use ChannelFactory?
ChannelFactory class is used to construct a channel between the client and the service without the need of a proxy. In some cases, you may have a service that is tightly bound to the client application. In such a case, you can reference the Interface DLL directly and use ChannelFactory to call your methods using that.
You could also refer following link to understand the difference between Channel Factory and Proxy class
http://ashishkhandelwal.arkutil.com/wcf/channelfactory-over-proxy-class-in-wcf/
The main advantage of the channelFactory is you can create the proxy at runtime dynamically on the fly. With SvcUtil (Add web reference in VS) you create the proxy at design time, so it's implementation is more static.