Closing a WCF Client – The Proper Way!
I’ve finally gotten around to putting a bit of time into Windows Communication Foundation (WCF), more of which to follow.
There’s one particular ‘feature’ I came across which doesn’t seem too well advertised, which I though would be worth sharing, related to how you close the connection.
Now, with most things in .Net that implement IDisposable (database connections, network connections, and so on), you simply have to call Close() or Dispose() – or more commonly, just put them in a Using statement:
The problem with this approach when it comes to WCF is that, unlike most things that you can Close(), when you call Close() on a WCF client, an exception might be thrown:
If you don’t know about the Using statement, it just calls Close() for you at the end of the code block so you don’t have to remember it. You can see the same thing happening here using Close() explicitly:
So, what’s happening here? Well, unlike some of the other things you might call Close() on, the WCF client is doing some actual work in this method. For a start, it’s connecting back to the service, which is something that could always fail due to network problems and so on – in the example above, I simply stopped the service before the client was closed. There may also be transactions to be finalised, and many other things I don’t know about.
But do we really need to care? Well, it’s hopefully not something that will happen a lot, but knowing the systems I’ve worked on, I’m sure it will happen at some point. And the chances are, you don’t really care about this exception – you’ve finished using the service anyway. So although it may be something you want to log, it probably isn’t a good enough reason to stop your app running, or disturb the user with a random message. It also means that your connection hasn’t been closed down properly, which could cause problems.
‘So what’s the fix already?!’, I hear you cry. Alright, I’m getting there! In the basic case, it’s as simple as putting a try-catch around the call to Close(), and calling Abort() on the client if something bad happens (which will make sure everything’s cleaned up properly):
And if you want to go the full hog and get one more tick in your ‘best practices’ box, you can follow this pattern (as pinched from Steve Smith’s blog):
Obviously, you can add logging in as appropriate.
This is admittedly a bit of a hassle, but you can always put it into a helper class or, as Steve suggests in the above blog, write an extension method on ICommunicationObject which will then work for all of your clients. I haven’t tried this, but it seems like a good approach.
So there you have it – one less thing to worry about with WCF! (Or is that one more thing to worry about..)