Periodically, the duplex Net.TCP connection between our Silverlight application and our WCF web service will enter the faulted state — for instance, due to transient network issues, or if the service crashes and restarts, things like that. When that happens, I’d like to catch this, and re-open the connection. Sounds straightforward, right? You should be able to do something like this:
private void Channel_Faulted(object sender, EventArgs e)
{
client.CloseCompleted += (sender, e) =>
{
if (e.Error == null)
client = CreateClient();
else
Debug.WriteLine(e.Error.ToString());
};
client.CloseAsync();
}
But when I try that the e.Error in the CloseCompleted handler has this exception:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
I’ve tried a whole bunch of variations on this same theme, including:
- Not closing the connection after it faults and just recreating it.
- Calling client.InnerChannel.Close() and/or client.ChannelFactory.Close() manually.
- calling client.InnerChannel.Dispose() and/or client.ChannelFactory.Dispose() manually.
- Lots of other stuff that I’ve forgotten now.
These strategies have resulted in a variety of errors, but none of have worked correctly, including the sort of non-Silverlight solutions mentioned, say, here or here (but all for regular CLR apps, not Silverlight). Surely this is a fairly straightforward thing to do, but apparently the channel caching is getting in my way. What am I missing? What’s the right way to do this in Silverlight? If this is a bug in Silverlight, what’s the right workaround?
As with most things that seem to be working in inexplicable ways, the problem was my fault. The actual code I’m working with is (not surprisingly, I hope) significantly more complicated than the simplified version I posted above. And it turns out that in my real code, in the particular code path that I was testing, the equivalent of this line was never being called:
In other words, the client wasn’t actually getting recreated after throwing a fault, and the errors I was running into primarily resulted from trying to re-use an old instance. Sorry for the fuss.