The correct handling of a WCF client’s life cycle

December 21, 2014, (updated on February 25, 2015), Software Development

The most intuitive way of handling a generated WCF client’s life cycle is by putting it into a using block:

using (var svc = new MyServiceClient())
{
    var result = await svc.SumAsync(1, 2);
}

Note: You should not use static or singleton client objects.

However, the problem with this code is, that IDisposable is not implemented correctly in the base class ClientBase. The problem is that the Dispose method always calls Close but Close may throw an exception. If this exception is thrown an additional call to Abort is needed but which is not made. Missing this Abort call may leave the client object in a faulted state and subsequent instances may be corrupted. You can find more details on this MSDN page; however, the presented solution is wrong which is discussed in this StackOverflow question.

To fix the dispose mechanism of the client instance, you have to “extend” the class using a partial implementation. This way you can override the IDisposable implementation and fix the original implementation. Just create a partial class for each generated WCF service client:

public partial class MyServiceClient : IDisposable
{
    private bool _isDisposed;

    /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. </summary>
    public void Dispose()
    {
        ServiceClientUtilities.Dispose(this, ref _isDisposed);
    }

    /// <summary>Finalizer. </summary>
    ~MyServiceClient()
    {
        Dispose();
    }
}

After extending the generated class with this code, you can safely use the code shown at the beginning of the article. The following class contains the reusable Dispose implementation:

/// <summary>Provides utility methods for WCF service clients. </summary>
public static class ServiceClientUtilities
{
    /// <summary>Disposes the service client. </summary>
    /// <param name="service">The service client. </param>
    /// <param name="isDisposed">The reference to a value indicating whether the service is disposed. </param>
    public static void Dispose(ICommunicationObject service, ref bool isDisposed)
    {
        if (isDisposed)
            return;

        try
        {
            if (service.State == CommunicationState.Faulted)
                service.Abort();
            else
            {
                try
                {
                    service.Close();
                }
                catch (Exception closeException)
                {
                    try
                    {
                        service.Abort();
                    }
                    catch (Exception abortException)
                    {
                        throw new AggregateException(closeException, abortException);
                    }
                    throw;
                }
            }
        }
        finally
        {
            isDisposed = true;
        }
    }
}

The shown utilities class can be downloaded here:

A complete sample solution can be downloaded from this GitHub repository.

Tweet about this on TwitterShare on FacebookEmail this to someoneShare on TumblrShare on LinkedIn

Tags: , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax