ebb
ebb

Reputation: 9397

WCF: ServiceClient + Dispose

This is what I understand from why we need to implement our own wrapper class for serviceClients (please correct me if I'm wrong):

The purpose of catching the exception in the Dispose() method is that .Close() may throw either a "CommunicationException" or "TimeoutException" - and to prevent the connection to hang you catch those two exceptions to use .Abort() which will change the state of the communication object to closed immediatley. - it would not make any sense to let the exception be unhandled because the nessecary calls to the methods have already been made since we're at the Dispose() part, and it would therefore be odd to throw an exception when the job actually is done as it should.

But why do:

public class ServiceClientWrapper<TServiceType> : IDisposable
{
    public TServiceType Channel { get; private set; }
    private readonly ChannelFactory<TServiceType> _channelFactory;

    public ServiceClientWrapper(string endpoint)
    {
        _channelFactory = new ChannelFactory<TServiceType>(endpoint);
        Channel = _channelFactory.CreateChannel();
        ((IChannel)Channel).Open();
    }

    #region Implementation of IDisposable

    public void Dispose()
    {
        try
        {
            ((IChannel)Channel).Close();
        }
        catch (CommunicationException ex)
        {
            ((IChannel)Channel).Abort();
        }
        catch (TimeoutException ex)
        {
            ((IChannel)Channel).Abort();
        }
        catch (Exception)
        {
            ((IChannel)Channel).Abort();
            throw;
        }
    }

    #endregion
}

When you can do:

public class ServiceClientWrapper<TServiceType> : IDisposable
{
    public TServiceType Channel { get; private set; }
    private readonly ChannelFactory<TServiceType> _channelFactory;

    public ServiceClientWrapper(string endpoint)
    {
        _channelFactory = new ChannelFactory<TServiceType>(endpoint);
        Channel = _channelFactory.CreateChannel();
        ((IChannel)Channel).Open();
    }

    #region Implementation of IDisposable

    public void Dispose()
    {
        ((IChannel)Channel).Abort();
    }

    #endregion
}

According to MSDN both .Close() and .Abort() will change the state of the communication object to "Closed"?

Upvotes: 0

Views: 2795

Answers (2)

Chris Dickson
Chris Dickson

Reputation: 12135

The point is that Close() will aim to close the entire communication channel gracefully, including any closing handshake required by the communication protocol, whereas Abort() is a rude and brutal tearing down of the client-side channel stack with no attempt to communicate the closure properly to the other side. Abort may therefore leave server-side resources still tied up on a connections which will not be used further.

So we always want to execute Close if possible, but we need to handle situations where things are so broken that trying to do a Close will cause a further exception.

Upvotes: 3

rene
rene

Reputation: 42494

Close method:

http://msdn.microsoft.com/en-us/library/ms405496.aspx

This method causes a CommunicationObject to gracefully transition from any state, other than the Closed state, into the Closed state. The Close method allows any unfinished work to be completed before returning. For example, finish sending any buffered messages.

Abort method Does the same ungracefully or as stated in the specs immediately. It will NOT finish anything still going on...

Upvotes: 2

Related Questions