Click here to Skip to main content
Click here to Skip to main content

Do not use "using" for WCF Clients

By , 17 May 2011
 
You know that any IDisposable object must be disposed using using. So, you have been using using to wrap WCF service’s ChannelFactory and Clients like this:
using(var client = new SomeClient()) {
. 
.
.
}
Or, if you are doing it the hard and slow way (without really knowing why), then:
using(var factory = new ChannelFactory<ISomeService>()) {
var channel= factory.CreateChannel();
.
.
.
}
That’s what we have all learnt in school right? We have learnt it wrong!
When there’s a network related error or the connection is broken, or the call is timed out before Dispose is called by the using keyword, then it results in the following exception when the using keyword tries to dispose the channel:
failed: System.ServiceModel.CommunicationObjectFaultedException : 
The communication object, System.ServiceModel.Channels.ServiceChannel, 
cannot be used for communication because it is in the Faulted state.
    
    Server stack trace: 
    at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
    
    Exception rethrown at [0]: 
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
    at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
    at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
    at System.ServiceModel.ClientBase`1.Close()
    at System.ServiceModel.ClientBase`1.System.IDisposable.Dispose()
There are various reasons for which the underlying connection can be at broken state before the using block is completed and the .Dispose() is called. Common problems like network connection dropping, IIS doing an app pool recycle at that moment, some proxy sitting between you and the service dropping the connection for various reasons and so on. The point is, it might seem like a corner case, but it’s a likely corner case. If you are building a highly available client, you need to treat this properly before you go-live.
So, do NOT use using on WCF Channel/Client/ChannelFactory. Instead you need to use an alternative. Here’s what you can do:
First create an extension method.
public static class WcfExtensions
{
    public static void Using<T>(this T client, Action<T> work)
        where T : ICommunicationObject
    {
        try
        {
            work(client);
            client.Close();
        }
        catch (CommunicationException e)
        {
            client.Abort();
        }
        catch (TimeoutException e)
        {
            client.Abort();
        }
        catch (Exception e)
        {
            client.Abort();
            throw;
        }
    }
}
Then use this instead of the using keyword:
new SomeClient().Using(channel => {
    channel.Login(username, password);
});
 
Or if you are using ChannelFactory then:
new ChannelFactory<ISomeService>().Using(channel => {    
    channel.Login(username, password);
});
Enjoy!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Omar Al Zabir
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom
Member

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberSrinivass Rayabandi23 Jan '13 - 1:40 
Good One
BugMy WCF Service hosted on iis is responding slow on client machine.memberPrem Gangwar15 Jun '12 - 7:34 
Hi Omar
 
i m using wcf service with wshttp binding. i test it on different machines its working fine in our environment. our machines are running on window 7 professional.
 
But when i deploy it on client machine its responding slow. client machin is running on window 7 home premium.
 
Please suggest me what to do for resolving this issue.
 
Thanks
Prem
QuestionWhat should be extension if operation returns value?memberMichael Freidgeim29 Jan '12 - 13:40 
What should be extension if operation returns value e.g for my current code
var fact = new ChannelFactory<IMyService>("MyService");
			var channel= fact.CreateChannel();
 
using (channel as IDisposable)
        {
            ret = channel.DecryptData(cipherText);
        }
Michael Freidgeim.
Blog: http://geekswithblogs.net/mnf/

AnswerRe: What should be extension if operation returns value?memberSTRICQ19 Apr '12 - 11:01 
var fact;
 
new ServiceClient().Using(channel => fact = channel.DecryptData(cipherText));

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 17 May 2011
Article Copyright 2011 by Omar Al Zabir
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid