IDisposable and WCF

Recently we’ve been separating our monolithic application into smaller systems which communicate via services.  We’re using WCF for this communication, and one of the things that we’ve quickly noticed is that WCF is, for whatever reason, not compatible with the usual best practice of wrapping IDisposable objects with a using() {…} block.  Personally, I don’t think resources should be marked IDisposable if you can’t simply use the using() statement.  The issue with the case of WCF’s client’s is that the call to Close() may throw an exception (a network error).  I have to believe that other disposable resources might also run into problems when cleaning up their connections, but somehow they’re still compatible with using().

Here’s an MSDN article showing the problem quite well:

Avoiding Problems with the Using Statement

If you do go the using() route, and errors occur, they end up throwing from the closing brace of the using() block, and being rather difficult to diagnose.  Here’s an example of such a WCF error with a using() statement.

It also includes the code for how to clean up after services correctly in light of the fact that they may blow up due to network errors.  Here’s the code that you shouldn’t use because WCF doesn’t work with it:

Here’s the code that you’re forced to use instead:

Isn’t that nice and clean?  Of course you can add it as an Extension Method to your ServiceClient.  If you do that, then you simply need to remember to use a finally block to call the code.  I’m not sure at that point that you’re any further ahead than if you just used the using() statement to begin with, but at least it eliminates the problem of having an exception thrown on the closing brace of the using block  and keeps the total amount of plumbing code that needs written to a minimum.  Your code then might look like this:

 

And here’s the extension method:

This method simply logs any exceptions via Debug.Print, but obviously you can adjust that to suit your exception handling procedures.

Note that if you *don’t* clean up these connections, they will come back to bite you.  One of our developers ran into an issue with our suite of integration tests for these services where they would work fine individually, but if you ran more than 10 of them, it would get real slow and start failing.  Turns out they weren’t being closed so after enough of them were opened, the rest would time out waiting for an open connection.  Yet another reason why testing pays off; I’m sure it would have been much harder for us to diagnose why our application was randomly slowing down and not working periodically (especially as this is for an unattended batch process).

  • Lars Wilhelmsen

    Hi,

    No need for a extension method, the generated client proxy is marked as partial, so you can add a .Dispose() method that takes the current State into account (and either .Close() or .Abort() the underlying channel.

    Best regards,

    Lars Wilhelmsen

    Connected Systems MVP

  • ssmith

    @Lars,

    That’s correct, but then I would have to do that for every generated proxy, whereas the more generic extension method can be used more broadly (and referenced from a utility assembly, if desired, rather than compiled into the proxy). Right?

  • Tim Rayburn

    You are correct that extending the class via partial would require you to do this for every single client. On the other hand, you could take the extension method move one step further than you did. This code snippet has enough Generics to make even my head spin, but works, and allows a quick lambda that returns your desired result to execute, strongly typed the entire way. The key here is the use of a Generic constraint.

    public static TResult SafeExecution<TExtension, TResult>

    (this TExtension myServiceClient,

    Func<TExtension, TResult> serviceAction)

    where TExtension : ICommunicationObject

    {

    TResult outValue;

    try

    {

    outValue = serviceAction.Invoke(myServiceClient);

    }

    finally

    {

    myServiceClient.CloseConnection();

    }

    return outValue;

    }

    Anyway, enjoy!

    Tim Rayburn

    (also a) Connected Systems MVP

  • Delf

    Instead of repeating myServiceClient.Abort(); in each catch section, use it inside the finally one.

  • New and Notable 290

    WCF/CSD/Azure I know I wrote about the &quot;broken WCF and IDisposable&quot; problem before and how we dealt with it at Neudesic but I can’t find it/them with Google. Here is a pointer to David Barrett’s (Neudesic) post about how we talked about it and

  • New and Notable 290

    WCF/CSD/Azure I know I wrote about the &quot;broken WCF and IDisposable&quot; problem before and how we dealt with it at Neudesic but I can’t find it/them with Google. Here is a pointer to David Barrett’s (Neudesic) post about how we talked about it and

  • IDisposable and WCF : Steve Smith’s Blog

    Thank you for submitting this cool story – Trackback from DotNetShoutout

  • barryd

    Jesse Ezell has a rather nifty lambda alternative at

    http://www.iserviceoriented.com/…/Indisposable+-+

    So you get the benefit of the close whern it falls out of scope :)

  • Damien McGivern

    There is no need for the scope of service proxy to extend outside out of the code block so I use the following code which is based on Jesse Ezell’s post mentioned above.

    public static void Using<ServiceT>(Action<ServiceT> action)

    where ServiceT : ICommunicationObject, new()

    {

    var service = new ServiceT();

    bool success = false ;

    try

    {

    action(service);

    service.Close();

    success = true;

    }

    finally

    {

    if(!success)

    {

    service.Abort();

    }

    }

    }

  • Dew Drop – February 12, 2009 | Alvin Ashcraft’s Morning Dew

    Pingback from Dew Drop – February 12, 2009 | Alvin Ashcraft’s Morning Dew

  • Friday Links #38 | Blue Onion Software *

    Pingback from Friday Links #38 | Blue Onion Software *

  • Links

    Links

  • consacepo

    You are correct that extending the class via partial would require you to do this for every single client. On the other hand, you could take the extension method move one step further than you did. This code snippet has enough Generics to make even my head spin, but works, and allows a quick lambda that returns your desired result to execute, strongly typed the entire way. The key here is the use of a Generic constraint.

    <a href="http://consacepo.blogspot.com">consacepo</a&gt;

  • consacepo

    No need for a extension method, the generated client proxy is marked as partial, so you can add a .Dispose() method that takes the current State into account (and either .Close() or .Abort() the underlying channel.

  • developer

    We are making WCF calls using the following Code.

    // In generated Proxy we have..

    public static ICustomer Customer

    {

    get

    {

    ChannelFactory<ICustomer> factory = new ChannelFactory<ICustomer>("Customer");

    factory.Endpoint.Behaviors.Add((System.ServiceModel.Description.IEndpointBehavior)new ClientMessageInjector());

    ICustomer channel = factory.CreateChannel();

    return channel;

    }

    }

    and we have Service Proxy class which has the methods like

    public static Datatable GetCustomerDetails(int id)

    {

    return Services.Customer.GetCustomerDetails(id);

    }

    Recently we found out that we need to "Close" the wcf connection and we are trying to find out away to do this without asking our developers to change too much of their code.

    Any Ideas ?

  • Sam Holder

    Isn’t there a problem with this extension method in that it doesn’t attempt to close the connection if it is in any other state than open, which means that if it is opening/created/faulted then it won’t be aborted, it’ll just be left alone