Rico Suter's blog.
 


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.



Discussion