When a single ClientBase<T>
instance is used for multiple WCF service calls, it can get a channel into a faulted state (ie. when the service is down).
I would like to heal the channel automatically when the service comes up again. The only way I found is to call the following code before each method call:
if (clientBase.InnerChannel.State == CommunicationState.Faulted)
{
clientBase.Abort();
((IDisposable)clientBase).Dispose();
clientBase = new SampleServiceClientBase();
}
I got the feeling that this isn't the right way to do it. Anyone got a better idea?
You can't. Once a channel is faulted, it's faulted for good. You must create a new channel. WCF channels are stateful (in a manner of speaking), so a faulted channel means the state may be corrupted.
What you can do is put the logic you're using into a utility method:
public static class Service<T> where T : class, ICommunicationObject, new()
{
public static void AutoRepair(ref T co)
{
AutoRepair(ref co, () => new T());
}
public static void AutoRepair(ref T co, Func<T> createMethod)
{
if ((co != null) && (co.State == CommunicationState.Faulted))
{
co.Abort();
co = null;
}
if (co == null)
{
co = createMethod();
}
}
}
Then you can invoke your service with the following:
Service<SampleServiceClient>.AutoRepair(ref service,
() => new SampleServiceClient(someParameter));
service.SomeMethod();
Or if you want to use the default parameterless constructor, just:
Service<SampleServiceClient>.AutoRepair(ref service);
service.SomeMethod();
Since it also handles the case where the service is null
, you don't need to initialize the service before calling it.
Pretty much the best I can offer. Maybe somebody else has a better way.
This is what I'm currently doing, but I can't say this is the best option either.
I recreate the proxy when an exception is caught on the call.
try
{
ListCurrentProcesses();
}
catch (TypeLoadException ex)
{
Debug.Print("Oops: " + ex.Message);
m_Proxy = new ProcessManagerProxy();
}
catch (EndpointNotFoundException endpointEX)
{
Debug.Print("Oops: " + endpointEX.Message);
m_Proxy = new ProcessManagerProxy();
}
catch (CommunicationException communicationEx)
{
Debug.Print("Oops: " + communicationEx.Message);
m_Proxy = new ProcessManagerProxy();
}