Handling timouts and unhandled exceptions

Topics: General Discussion Forum, July and December Releases Forum, Service Factory Modeling Edition Forum
Mar 10, 2008 at 1:10 PM
Does anyone have any good solutions for handling timeouts and unhandled exceptions for a WCF service?

When things like a timeout happens the WCF service goes into a faulted state and the proxy cannot be used again by the client before a new one is created. I have read an article by Michele Leroux Bustamante about building a proxy wrapper and the idea sounds good, but I'm not able to put this idea into practice so I want to hear if someone have had any experience with this?

There must be some good ways to handle these kinds of problems because they are very common and the must be handled in a production environment.

NB! For the moment Im using WSSF december 2006 with Visual Studio 2005, but I guess this problem also counts for the new ME version of WSSF?
Mar 10, 2008 at 4:34 PM
You could make your own proxy with ChannelPool, which will be created with ChannelFactory and than inspect channel state . If the channel is in Faulted state

(channel as IClientChannel).State== CommunicationState.Faulted

, then get another one channel from pool. In addition this enables better performances, because if you have already generated channels you will have time savings in work because of Indigo costs during the channel initialization.. Only you will have some time losts because of channel pool warm up


Regards
Mar 11, 2008 at 11:12 AM
Yes, I could. And its a great idea. But how do you implement this? Do you have some more details for me? If this is done in a general manner it could be put in a receipt, right? There should be a receipt in WSSF that created a general proxy wrapper.
Could you please send me some code or some more hints on how this is done? My autgenerated proxy now inherit from System.ServiceModel.ClientBase<T> and there are some details that need to be sorted out here.... I dont have the hole picture here...
Mar 11, 2008 at 1:34 PM
My team generates ServiceAgent project (through factory generation), and this one project has ChannelPool. For each method(operation) from model our customization factory generates proxy operation which has in it's body ChannelPool.GetChannel call and after execution release channel

e.g. :

ISomeContrct channel = ChannelPool.GetChannel ();
channel.Execute();
ChannelPool.ReleaseChannel (channel);

and now you have to write your own class for ChannelPool and channel generation, look forward for ChannelFactory class and some examples. I couldn't give you more informations because of companies security policy.

R
Mar 12, 2008 at 1:15 PM
Well, what is ChannelPool? Is it a WCF-term or something your team has developed?

Does anybody else has some god solution on this problem? I guess any WCF service that is running in an production environment must have this sorted out so somebody must have done something smart on this. I'll continue to search the Web because its stupid if everyone must invent the wheel every time.

Anyway, thank you Cucciolo for trying to help me, but you didn't give me better ideas than the article by Michele that I mentioned in my first post. :-)

Anybody?
Mar 12, 2008 at 2:03 PM
ChannelPool is one static class that handle operations proxy channels. Now it's static. When first instance of client calls service static constructor generates pool (kind of collection, queue or other one).. of IContract channels. Number of channels depends on yours system. Channel could be generated through ChannelFactory and than you have clients proxy with collection of opened channels.. then as i wrote in precedent post just call this ChannelPool class collection and get channel, after operation's execution release that channeland turn back it in collection.. in addition with this you have just to inspect does the getted or released channel in "correct state" if it's not create a new one.

I hope that's the explanation better ;)
Mar 19, 2008 at 2:05 PM
On our project we include a little #region block of code that handles the various types of error that might be thrown by WCF, including timeouts, and converts them to all to a custom exception that contains information about the type of error. That way we can just copy and paste the region into all our wcf client calls. And we tend to make sure that all our exceptions raised in the service are raised as specific faultexceptions- when you raise a fault exception the service does not become faulted (I think).

I realise this does not solve the problem of what to do when the service becomes 'faulted', but in our system it is the responsibility of the the client code to determine what to do when there's an error- whether to try it out again, etc. In that case they'd be calling the same method again, and a new channel would be opened.

The first thing is that we're not using a 'using' block for our proxy, because if the service becomes faulted then jumping out of the block also causes an exception, which hides the original problem (or at least it did in .NET 3). So we're using standard try/catch/finally. So then we have a handler for timeouts, one for any of our specific fault exceptions, one for general fault exceptions (which we would never expect), and one for other communications problems.

We've got a web system so we're opening a channel each time. I realise this is perhaps not the best performance, and I guess there is some way that we can create a connection pool for the users of the web app as a whole, but since .NET 3.5 came along, WCF performance has improved dramatically so we're not at the stage of implementing that yet.

So to the code:

OurServiceManager.OurServiceClient proxy = new OurServiceManager.OurServiceClient();
try
{
OurServiceManager.OurDataContract request = new OurServiceManager.OurDataContract ();
request.Afield= xxxx;

response = proxy.SomeMethod(request);


}
#region StandardErrorHandler
catch (TimeoutException timeProblem)
{
ExceptionHelper.HandleTimeoutException(timeProblem);
}
catch (FaultException<OurSpecificFault> ourSpecificFault)
{
ExceptionHelper.HandleOurSpecificFault(ourSpecificFault);
}
catch (FaultException faultEX)
{
ExceptionHelper.HandleFaultException(faultEX);
}
catch (CommunicationException commProblem)
{
ExceptionHelper.HandleCommunicationException(commProblem);

}
finally
{
// Make sure our proxy is closed off
if (proxy.State == CommunicationState.Faulted)
{
proxy.Abort();
}
else
{
proxy.Close();
}
}
#endregion
Mar 19, 2008 at 2:49 PM
Take a look at this thread: http://www.codeplex.com/servicefactory/Thread/View.aspx?ThreadId=23941