Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual WCF Client behaviour

Tags:

c#

wcf

wpf

I have an SOA application that uses a duplex WCF service hosted within a Windows Service. The client itself is a WPF application.

I'm seeing unusual behaviour on closing and restarting the client application. If I start a new instance after closing one, nothing visibly appears to happen. However, checking task manager shows the new instance is running as a background process. If I try to start another new instance of the client application, it will display the error screen I've written - stating an error with the service. Investigation has shown that the client cannot create a new instance of the service callback channel because another application has already registered the URL. This is a System.ServiceModel.AddressAlreadyInUseException.

If I then end the background client task in task manager, my client displaying the error message is then able to connect to the service and run as normal. I have also noticed that if I close the background task before starting a new instance, the new instance will also not appear.

My concern here is that this is not useable and feels like a real hassle for users. What could be going wrong? It seems as if something is not cleaning up unmanaged resource but I've used ANTS and can't identify it. The client is created as:

IServiceCallback callback = new Callback();
_context = new InstanceContext(callback);

_channelFactory = new DuplexChannelFactory<IMyService>(_context, binding, endpoint);

_proxy =
    _channelFactory.CreateChannel();
((ICommunicationObject)_proxy).Open(TimeSpan.FromSeconds(5));

The Service's constructor uses the following code:

_callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();

var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
    commObject.Faulted += ChannelFaulted;
    commObject.Closing += ChannelClosing;
    commObject.Closed += ChannelClosed;
}

OperationContext.Current.Channel.Faulted += ChannelFaulted;
OperationContext.Current.Channel.Closed += ChannelFaulted;

Before closing, the client calls the service's Disconnect method, which does:

var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
    commObject.Faulted -= ChannelFaulted;
    commObject.Closing -= ChannelClosing;
    commObject.Closed -= ChannelClosed;
}

OperationContext.Current.Channel.Faulted -= ChannelFaulted;
OperationContext.Current.Channel.Closed -= ChannelFaulted;

Finally, the client closes the channels like this:

foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
    incomingChannel.Close();
}
try
{
    var proxy = _proxy as IChannel;
    if (proxy != null)
    {
        proxy.Close();
    }
}
catch (Exception)
{
    _channelFactory.Abort();
}

Why am I seeing this unusual behaviour? Is there something I'm missing to close the channel or something I'm doing wrong to create it? Or is it likely that there must be an issue elsewhere in my code that keeps the channel or session alive?

**UPDATE: ** I have been trying a few things and found out that if I start a client instance, close it, then leave it for an hour, I can start another instance with no issue. I've also discovered that if I restart the Windows Service after creating and closing an instance of the client application then I'm also able to create another in those circumstances.

**UPDATE 2: ** Stepping through, I can see that the incomingChannel.Close() does not complete and does not throw an error. I've removed that section and also find proxy.Close() does not complete and does not throw an exception. I've tried using the overloads and added a timeout, but no timeout exception is being thrown. The Service's Dispose() method is not hit at all.

like image 459
MrShoes Avatar asked Aug 26 '14 10:08

MrShoes


1 Answers

Try closing your channel factory too.

proxy.ChannelFactory.Close();
proxy.Close();
like image 179
iamkrillin Avatar answered Sep 30 '22 17:09

iamkrillin