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
ChannelFactory channel =
   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.


About the Author

SM Altaf

Mendhak is a web developer and a Microsoft MVP who works with ASP.NET and PHP among the usual array[] of web technologies. He is also rumored to be a three eyed frog, but the evidence is lacking. He can be contacted via his website, www.mendhak.com.