Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How important is to call dispose on a WCF ChannelFactory<T> and T channel object right after usage?

Tags:

c#

.net

oop

wcf

Developers like to write as short and simple code as possible. We are invoking WCF services in C# and wondering if the following intuition is right or wrong. One way of using ChannelFactory code is:

var factory = new ChannelFactory<IService>("Endpoint");
var client = factory.CreateChannel();

client.DoSomething();

((IClientChannel)client).Close();
factory.Close();

Other way (a bit cleaner) is using a wrapper object (for factory and channel) which implements IDisposable where disposes both and used in using block:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
    svcWrapper.Channel.DoSomething();
}

Here, having to call the wrapper's property might be a bit annoying for developers. Basically also could be:

using (ServiceWrapper<IService> svcWrapper = new ServiceWrapper<IService>("Endpoint")) {
    IService client = svcWrapper.Channel;
    client.DoSomething();
}

(I also found this MSDN article saying that the using block can hide exceptions)

What the developers might prefer is:

 IService client = new ServiceWrapper<IService>("Endpoint").Channel;
 client.DoSomething();

From the book C# 5.0 in a Nutshell:

A popular pattern is to have the finalizer call Dispose. This makes sense when cleanup is non-urgent and hastening it by calling Dispose is more of an optimization than a necessity.

If I add this to my ServiceWrapper (C# Finalize/Dispose pattern):

public void Dispose() {
    Dispose(true);
    GC.SuppressFinalize(this);
}

~ServiceWrapper() {
    Dispose(false);
}

Then GC will eventually call Dispose and do the things that need to be done. i.e.:

public void Dispose(bool disposing) {
    if (disposing) {
        if (_channel != null) {
            ((IClientChannel)_channel).Close();
        }
        if (_factory != null) {
            _factory.Close();
        }

        _channel = null;
        _factory = null;
    }
}

I have a feeling that this is not a good practice to use with WCF ChannelFactory<T> and T channel, but I don't have a good explanation which would scare the developers away form using it. Can you guys explain pls?

I can't say it's not working, I tried it and it works fine. I can't see any noticeable performance difference or similar... I cannot give other explanation than "You don't know when the finalizer gets called." Thanks!

like image 840
DDan Avatar asked Jul 27 '15 07:07

DDan


People also ask

How do I dispose of WCF client?

Anyone utilizing the client can wrap it into an ordinary using block. If the client is in a clean state a graceful close is done. If the client is in a faulted state a hard abort is done. If an exception is thrown by a service method the client is placed in the faulted state.

What is channel in WCF service?

Channels provide a low-level programming model for sending and receiving messages. This programming model relies on several interfaces and other types collectively known as the WCF channel model.


1 Answers

Well, the only thing the Dispose method does is explicitly close the connection. That is all. You can see for yourself in the reference source. Also, ClientBase<T>, the base class for the connection does the same.

That said, if you call Close yourself there isn't an actual need at the moment to call Dispose at all, although I would argue that you really should Dispose, just to be future proof. Also this can be a fail-safe for errors occurring which may prevent Close to be called.

like image 136
Patrick Hofman Avatar answered Sep 19 '22 15:09

Patrick Hofman