TIP: Closing your WCF Connections properly
In a previous tip, you looked at how you could use ChannelFactory or Proxy Classes to talk to a WCF service. Now you can have a look at how to properly close of these connections.
If you've used Visual Studio to generate a WCF proxy class for one of your WCF services, go on and have a look at it now. In it, have a look at the generated client class:
public partial class StockServiceClient : System.ServiceModel.ClientBase<StockService.IStockService>, StockService.IStockService {
...
The client that you use in your main code inherits from ClientBase<>. Looking at ClientBase on MSDN, you see that it implements IDisposable. As with most other classes implementing IDisposable, it is tempting to use the C# using statement for your WCF clients.
//It's tempting, but don't do this:
using(StockService.StockServiceClient client = new StockService.StockServiceClient(
"StockBasicHttpEndpoint", stockServiceUrl))
{
client.GetStockIdByName("MSFT");
}
And as you know, the using block will automatically call client.Dispose() when it's done. There's a problem with it though — with ClientBase, the Dispose() method makes a call to Close(). When the ClientBase's Close() method is called, a web service call actually goes out to the WCF service, informing it that the connection session is no longer required. This appears counter-intuitive, but it was done by design. The problem with this mechanism is that when the Close() method is called, an exception can be thrown. After all, it involves yet another network call to a web service. It's for this reason that the using statement isn't recommended with WCF clients.
Instead, you should attempt to Close() it in a try-catch block, with the catch block performing an Abort()
//Call your web service as usual.
StockService.StockServiceClient client = new StockService.StockServiceClient(
"StockBasicHttpEndpoint", stockServiceUrl);
string StockId = client.GetStockIdByName("MSFT");
//Done with the service, let's close it.
try
{
if (client.State != System.ServiceModel.CommunicationState.Faulted)
{
client.Close();
}
}
catch (Exception ex)
{
client.Abort();
}
The same thing applies to your ChannelFactory, if you use one — and the code to close it is exactly the same.
//Create channel from factory ChannelFactorychannel = new ChannelFactory<IService1>("bindingName"); IService1 client = channel.CreateChannel(); client.DoWork(); //Done with the service, let's close it. try { if (client.State != System.ServiceModel.CommunicationState.Faulted) { client.Close(); } } catch (Exception ex) { client.Abort(); }
So the points made here, very briefly, are
- Don't use 'using' with your WCF client classes
- .Close() the client in a try-catch block and .Abort() it if an exception occurs.

Comments
I don't think so either!
Posted by Mark on 04/17/2012 07:19amYou are better off aborting the object in the 'Finally' part of the try-ctach. In your example you won't be able to abort unless exception is thrown. What if no exception is thrown but the transaction lasts forever? You then have to realy on yout timeout quota, which effectively (in the case of a large app) may end up in multiple sessions lingering and waiting to be disposed off. Please remove this post - it is nto right and may be confusing for some readers. Regards.
ReplyNo, I don't think so.
Posted by JerryNixon on 03/09/2011 03:12pm1. With your TIP the method call (cal named it DoWork()) may fail, causing the flow to exit the method and bypass the possibility of the Abort() call in your catch { client.Abort(); }. 2. WIth your TIP the method call may pass, but the state may be faulted, but Abort() cannot be called because an exception is required. It seems to me that you should: 1. Move the method call into your try { } block. 2. Remove the (State != Faulted) if statement. Are you sure about your suggestion here?
Reply