I have been handing the closing and aborting of channels this way:
public async Task<MyDataContract> GetDataFromService()
{
IClientChannel channel = null;
try
{
IMyContract contract = factory.CreateChannel(address);
MyDataContract returnValue = await player.GetMyDataAsync();
channel = (IClientChannel);
return returnValue;
}
catch (CommunicationException)
{
// ex handling code
}
finally
{
if (channel != null)
{
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}
else
{
channel.Close();
}
}
}
}
Assume only a single thread uses the channel. How do we know the channel will not fault right after checking the state? If such a thing were to happen, the code would try to Close() and Close() will throw an exception in the finally block. An explanation about why this is safe/unsafe and examples of a better, safer way would be appreciated.
Yes, the state is a "snapshot" of the current state when you get it. In the time between when you access the CommunicationState and when you go to make a logical decision based on it, the state can have easily changed. A better WCF pattern is:
try
{
// Open connection
proxy.Open();
// Do your work with the open connection here...
}
finally
{
try
{
proxy.Close();
}
catch
{
// Close failed
proxy.Abort();
}
}
In this way you don't rely on the state in order to make decisions. You try to do the most likely thing (a healthy close) and if that fails (which it will when the CommunicationState is Faulted), you call Abort to ensure proper cleanup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With