Duplex channel Faulted event does not rise on second connection attempt

3.4k views Asked by At

I have regular net.tcp WCF service client, and regular net.tcp duplex (i.e. with a callback) WCF service client. I have implemented some logic to constantly reinstantiate the connection in case a service has faulted.

They are created in the exactly same way:

FooServiceClient Create()
{
    var client = new FooServiceClient(ChannelBinding);
    client.Faulted += this.FaultedHandler;
    client.Ping(); // An empty service function to make sure connection is OK
    return client;
}

BarServiceClient Create()
{
    var duplexClient = new BarServiceClient(new InstanceContext(this.barServiceCallback));
    duplexClient.Faulted += this.FaultedHandler;
    duplexClient.Ping(); // An empty service function to make sure connection is OK
    return duplexClient;
}

public class Watcher
{
public Watcher()
{
    this.CommunicationObject = this.Create();
}

ICommunicationObject CommunicationObject { get; private set; }

void FaultedHandler(object sender, EventArgs ea)
{
    this.CommunicationObject.Abort();
    this.CommunicationObject.Faulted -= this.FaultedHandler;
    this.CommunicationObject = this.Create();
}
}

The FaultedHandler() aborts the channel and recreates it using the code above.

The FooServiceClient reconnection logic works just fine, it is being reconnected after many faults. Whereas, almost the same but duplex BarServiceClient receives Faulted event only from the first BarServiceClient instance, i.e once.

Why only the firsts instance of duplex BarServiceClient gets faulted event? Are there any workarounds?


A similar non answered question: WCF Reliable session without transport security will not faulted event on time

1

There are 1 answers

0
Vasyl Boroviak On BEST ANSWER

After two days on the war against WCF I have found a workaround.

Sometimes WCF fires Faulted event, but sometimes it do not. However, the Closed event is always fired, especially after the Abort() call.

So I call Abort() in FaultedHandler which effectively fires Closed event. Subsequently, the ClosedHandler performs the reconnection. In case when Faulted is never fired by framework, the Closed event is always fired.

BarServiceClient Create()
{
    var duplexClient = new BarServiceClient(new InstanceContext(this.barServiceCallback));
    duplexClient.Faulted += this.FaultedHandler;
    duplexClient.Closed += this.ClosedHandler;
    duplexClient.Ping(); // An empty service function to make sure connection is OK
    return duplexClient;
}

public class Watcher
{
public Watcher()
{
    this.CommunicationObject = this.Create();
}

ICommunicationObject CommunicationObject { get; private set; }

void FaultedHandler(object sender, EventArgs ea)
{
    this.CommunicationObject.Abort();
}

void ClosedHandler(object sender, EventArgs ea)
{
    this.CommunicationObject.Faulted -= this.FaultedHandler;
    this.CommunicationObject.Closed -= this.ClosedHandler;
    this.CommunicationObject = this.Create();
}
}