7
votes

I'm trying to implement a reconnect logic for a wcf client. I'm aware that you have to create a new channel after the current channel entered the faulted state. I did this in a channel faulted event handler:


internal class ServiceClient : DuplexClientBase, IServiceClient
{
  public ServiceClient(ICallback callback, EndpointAddress serviceAddress)
   : base(callback, MyUtility.GetServiceBinding("NetTcpBinding"), serviceAddress)
  {
   // Open the connection.
   Open();
  }

  public void Register(string clientName)
  {
    // register to service
  }

  public void DoSomething()
  {
    // some code
  }
 }

 public class ClientApp
 {
  private IServiceClient mServiceClient;

  private ICallback mCallback;

  public ClientApp()
  {
   mServiceClient = new ServiceClient( mCallback, new EndpointAddress("someAddress"));

   mServiceClient.Register();

   // register faulted event for the  service client
   ((ICommunicationObject)mServiceClient).Faulted += new EventHandler(ServiceClient_Faulted);
  }

  void ServiceClient_Faulted(object sender, EventArgs e)
  {
   // Create new Service Client.
   mServiceClient = new ServiceClient( mCallback, new EndpointAddress("someAddress"));

   // Register the EI at Cell Controller
   mServiceClient.Register();
  }

  public void DoSomething()
  {
   mServiceClient.DoSomething();
  }
 }

But in my unit test I still get a "The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state" exception.

Is it possible that the callback channel is still faulted and if yes how can I replace the callback channel?

2
Could you specify what your unit test does when it triggers the exception?d91-jal
In my unit test I creates a service host and a client instance. I register the client on the service and then I stop the service by setting the reference to null. After that I wait 20 seconds (I'm using a reliable session with an InactivityTimeoutof 10 seconds, so I'm sure the connection is lossed after 20 seconds) and then I call the DoSomething() method on the client. Now I recreate the service and expect the client to reconnect. In that moment I get the exception.phatoni

2 Answers

5
votes

so far I have experienced that a WCF connection needs to be recreated on fault - there doesn't seem to be a way to recover it otherwise. As for when a fault occurs, the method seems to fire fine, but often it fires and cleans up the WCF connection (establishing a new one, etc) as the current request is going through - causing this to fail - especially true on timeouts.

A couple of suggestions: - If it is timeout related, keep track of the last time a call was made and a constant containing the timeout value. If the WCF connection will have been dropped due to inactivity, drop it and recreate it before you send the request over the wire. - The other thing, it looks like you are not re-adding the fault handler, which means the first fault will get handled, but the second time it faults it will fall over without a handler cause no new one has been attached.

Hope this helps

0
votes

Have you tried to reset the communications channel by calling mServiceClient.Abort in the Faulted event handler?

Edit:

I see that you do not reinitialize the mCallback object in your recovery code. You may need to assign it to a new instance.