Don’t Wrap Wcf Service Hosts or Clients in a Using Statement
Posted by Dan Rigsby on February 26th, 2008
Ok, this article is going to go against everything your mother taught you about cleanly disposing of your objects. Didn’t she always say, “Always dispose of your resources when you are finished with them. And scope it with a using statement if you can!”? My mother practically beat that into me growing up and she would probably disown me if she read this post.
So at first glace I would think that this is how I might create a service and client in Wcf:
using (ServiceHost serviceHost = new ServiceHost( typeof(MyService), new Uri("http://localhost:8000/MyService"))) { serviceHost.Open(); } using (ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>()) { channelFactory.Open(); }
Don’t tell your mother, but I’m going to tell you right now, “Don’t do this!“.
Now one comment you might have is, “Dan, I don’t see a Dispose method on the ServiceHost or ChannelFactory anyway.” Well, I’m going to give you a bonus tip. Sometimes the .Net gods change the protection level of the Dispose method so that it doesn’t show up. Don’t believe me? Check out the Msdn article for ServiceHost and ChannelFactory (and some other classes). It clearly shows that they implement IDisposable, but they are marked as “private” (sometimes they mark it “protected”). Using a “using” statement will basically treat it like the following which is legal since it implements IDisposable even though the protection level is not public:
ServiceHost serviceHost; try { serviceHost = new ServiceHost( typeof(MyService), new Uri("http://localhost:8000/MyService"))); serviceHost.Open(); } finally { if (serviceHost != null && serviceHost is IDisposable) { ((IDisposable)serviceHost).Dispose(); } }
If your call to Open() on the service host fails, then the finally block will still be executed. This results in Dispose being called. The reason this is bad is because of what the Dispose method actually does. It tries to call Close(). Now since we failed in Open, the connection hasn’t been established, so this will throw a InvalidOperationException and a CommunicationObjectFaultedException. This is not desirable, but these are considered “Expected Exceptions”, so they are left up to the developer to handle. The correct way to setup the servicehost and client is to handle the “Expected Exceptions” gracefully and propagate any “Unexpected Exceptions”.
So how should you open and close service hosts and clients? Something like what I have below is considered “best practice”:
ServiceHost serviceHost = null; try { serviceHost = new ServiceHost( typeof(MyService), new Uri("http://localhost:8000/MyService")); serviceHost.Open(); // Do work... serviceHost.Close(); } catch (CommunicationException) { if (serviceHost != null) { serviceHost.Abort(); } } catch (TimeoutException) { if (serviceHost != null) { serviceHost.Abort(); } } catch (Exception) { if (serviceHost != null) { serviceHost.Abort(); } throw; } ChannelFactory<IMyService> channelFactory = null; try { channelFactory = new ChannelFactory<IMyService>(); channelFactory.Open(); // Do work... channelFactory.Close(); } catch (CommunicationException) { if (channelFactory != null) { channelFactory.Abort(); } } catch (TimeoutException) { if (channelFactory != null) { channelFactory.Abort(); } } catch (Exception) { if (channelFactory != null) { channelFactory.Abort(); } throw; }
If you notice, I am catching a CommunicationException and not a CommunicationObjectFaultedException. This is ok because it inherits from CommunicationException, so it will be caught along with any other exceptions that derive from CommunicationException.
I’m sure you are thinking something like, “Why doesn’t dispose automatically handle this”. Honestly that is a good question. It’s probably part of the reason why they make the Dispose() method private. I am sure there is a good reason, but this is not intuitive to the developer and doesn’t follow the well understood standards that we have been taught. So remember to always open and close both your service host and clients using something similar to the mechanism show above. This will help you gracefully handle these “expected exceptions”.
You could even use a wrapper object to handle this for you. Since both ServiceHost and ChannelFactory derive from CommunicationObject, you could build a wrapper around this. The wrapper would allow you to call Close() or Dispose() with the desired exception handling and aborting. If you wanted to do something custom when these “excepted exceptions” are thrown you would have to modify the wrapper or not use a wrapper at all. Here is a example of a wrapper you could use:
public class CommunicationObjectWrapper : IDisposable { private System.ServiceModel.Channels.CommunicationObject m_CommunicationObject; public System.ServiceModel.Channels.CommunicationObject CommunicationObject { get { return m_CommunicationObject; } } public CommunicationObjectWrapper( System.ServiceModel.Channels.CommunicationObject communicationObject) { m_CommunicationObject = communicationObject; } public void Close() { if (m_CommunicationObject != null) { m_CommunicationObject.Close(); } } public void Dispose() { if (m_CommunicationObject != null) { try { ((IDisposable)m_CommunicationObject).Dispose(); } catch (CommunicationException) { m_CommunicationObject.Abort(); } catch (TimeoutException) { m_CommunicationObject.Abort(); } catch (Exception) { m_CommunicationObject.Abort(); throw; } } } }
These msdn articles helps explain these issues:
http://msdn2.microsoft.com/en-us/library/aa355056.aspx
http://msdn2.microsoft.com/en-us/library/aa354510.aspx

















February 27th, 2008 at 1:19 pm
Here is a newsgroup discussion that gives some insight on the design decisions regarding Dispose()
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=855018&SiteID=1
May 4th, 2008 at 8:59 am
Thanks for the great read, the issue here is obviously something wrong with the implementation of IDisposable pattern that we always expect for the unmanaged resource to close or dispose safely – appearantly this is not the case with WCF. Another way of solution could have been writing your own ClientBase and handling communication fault exception, do what you need when that exception has arisen, and safely continue to use of “using” or “close” your objects off. what do you think ?
Thanks again.
Sidar
November 13th, 2008 at 6:08 am
[...] check out a post by Dan Rigsby that goes into more detail. http://www.danrigsby.com/blog/index.php/2008/02/26/dont-wrap-wcf-service-hosts-or-clients-in-a-using... Published Thursday, November 13, 2008 6:29 AM by sweisfeld Filed under: C#, .NET, SOA, VB.NET, [...]
May 1st, 2009 at 4:33 pm
Thanks, I ended up wrapping the channel on client side like so;
public class ServiceWrapper : IDisposable
{
public ServiceWrapper()
{
_channelFactory = new ChannelFactory(typeof(T).FullName);
Channel = _channelFactory.CreateChannel();
}
private ChannelFactory _channelFactory;
public T Channel { get; private set; }
#region IDisposable Members
public void Dispose()
{
if (_channelFactory != null)
{
try
{
((IDisposable)_channelFactory).Dispose();
}
catch (CommunicationException)
{
_channelFactory.Abort();
}
catch (TimeoutException)
{
_channelFactory.Abort();
}
catch (Exception)
{
_channelFactory.Abort();
throw;
}
}
}
#endregion
}
usage
using (var wrapper = new ServiceWrapper())
{
wrapper.Channel.DoSomething();
}