vtcoder

I have a client class that abstracts a WCF client proxy. This class currently does not take advantage of any pooling. Each instance of this client class uses its own channel factory to create a channel/proxy instance. When the client class is disposed, then the underlying channel/proxy is closed.

My question is, should I also be closing the ChannelFactory Since each channel factory only has one channel/proxy, and it is already closed by the time I would potentially close the factory, am I gaining anything by explicitely closing the factory

In some preliminary performance testing, when I explicitely closed the factory in the dispose method of my class, it added about 10% time compared to when I did not explicitely close this. This was over 12000 consecutive calls to the server, and the time went from about 150 seconds to about 165 seconds.

My understanding is that if I keep the factory around and create multiple channels/proxies from one factory instance, then I can take advantage of connection pooling, and then calling close on the factory would have the same affect as calling close on all of its current live channels/proxies.

I do plan on changing things in the future to take advantage of pooling, but for now can someone tell me is there any advantage in closing the factory explicitely if it will only ever have one channel/proxy that is already closed I'm guessing that there is not, but I wanted to make sure there was nothing I'm unaware of.

Thanks



Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

BenK

Channel factories are heavy and should be cached and used by all proxies of that type as a static.

re question - You should close it when it will never be used again , this may release resource and close underlying connections . This explains your perf difference.

Anyway you really should be using a factory for all proxies to a particular service,

Regards,

Ben





Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

vtcoder

I agree. Ideally we would just use the static ChannelFactory. I'm just trying to find out what the best solution is given less than ideal limitations. In the next release that is the first change I'm going to make (making the ChannelFactory static).





Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

BenK

In that case i would close it more to clean things up , i dont like trusting GC disposes, if i can cleeanly close things.

Regards,

Ben





Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

vtcoder

That was my initial thought as well, so I changed the class to cleanup both the proxy and the factory. Then I reran some performance tests and it seemed to result in a 10% degradation. Not a deal breaker necessarily, but it was significant enough to prompt me to dig a little deeper, so here I am Smile

I'm guessing that not cleaning up the factory with each class will result in less efficient use of memory, but it also seems to result in less processor time, at least during heavy use. I guess I was trying to find out if not cleaning up the factory raised any red flags for anyone. I didn't want to introduce a known problem for lack of researching it.

I think I'm going to look into changing the code to use a static channel factory and have our class use a factory pattern as well. If this isn't too big of a change, I may be able to squeeze it in in time. Regardless, that's the path I want to take. It's just a question of when. The more I think about the 2 options now (leaving a bunch of undisposed objects, or introducing a 10% performance degradation) the more I want to try the static factory.

Having said all of that, if anyone has any further insight into the impact of not closing a bunch of channel factories, I'd still be interested in hearing it.

Thanks





Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

BenK

Considering you are restarting the factory cleaning up resources is critical if the perfornmance loss is an issue you should cache or use static factories.

I think the behaviour of not closing it and leaving it to dispose will depend on the transport in question.

Here is one i use note its not ideal as it requires the caller to close the connection ( some dispose support would be nice) but at leats its stronlgly typed so we are closing the right proxy. There are also more elgant solutions around that pool the connection object.

public static class ProxyHelper<T>
{
private static ChannelFactory<T> innerClient;


private static Object lockObj = new object();

private static string endPointName = "*";

static public T GetChannel()
{
ChannelFactory<T> cf = Client; // do not lock or will get dead lock
lock (lockObj)
{
T channel = default(T);
try
{
channel = cf.CreateChannel();

if (((ICommunicationObject)channel).State == CommunicationState.Faulted)
throw new ArgumentException("Channel is faulted");


((ICommunicationObject)channel).Open();
//#if Debug
// ((ICommunicationObject)channel).Closed += new EventHandler(ProxyHelper_Closed);
return channel;
}
catch (Exception)
{
if (cf.State != CommunicationState.Opened)
{
cf.Abort();

innerClient = null;
}
if (channel != null && ((ICommunicationObject)channel).State != CommunicationState.Opened)
{
((ICommunicationObject)channel).Abort();
}

throw;
}
}

}

static void cf_Faulted(object sender, EventArgs e)
{
if (innerClient != null)
innerClient.Faulted -= new EventHandler(cf_Faulted);
innerClient = null;

}

static public void Close(T channel)
{
if (channel != null)
{
// ((ICommunicationObject)channel).Closed -= new EventHandler(ProxyHelper_Closed); // remove handler
((ICommunicationObject)channel).Close();
}
}


static private ChannelFactory<T> CreateProxy()
{

ChannelFactory<T> cf = new ChannelFactory<T>(endPointName); // used reflector to find this
cf.Faulted += new EventHandler(cf_Faulted);
cf.Open();
return cf;

}

private static ChannelFactory<T> Client
{
get
{
lock (lockObj)
{
if (innerClient == null)
innerClient = CreateProxy();

}
return ProxyHelper<T>.innerClient;
}

}

static public string EndPointName
{
get { return endPointName; }
set { endPointName = value; }
}

public static ChannelFactory<T> InnerChannelFactory
{
get { return ProxyHelper<T>.innerClient; }

}

} //ProxyHelper<T>

Regards,

Ben





Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

BSOD2600

BenK, you mind giving some examples how to use the ProxyHelper class I've been looking for a good way to manage a single instance of a WCF service proxy among Windows Form app.




Re: Windows Communication Foundation (Indigo) Question about closing ChannelFactory

BenK

A bit late .. Note the proxy i use is not great code wise as it doesnt reuse proxies ( but it does reuse the unrelying connection ,can retry ) . Im still looking for a better one.

ITrackingService service = ProxyHelper<ITrackingService>.GetChannel();

try
{
service.UploadNewTrackings(message);
}
finally
{
ProxyHelper<ITrackingService>.Close(service);
}

Regards,

Ben