10

I've been wrapping all the code that invoke WCF calls within an using statement in a thought that the object will be disposed properly. When I'm googling for an exception "Http service located at .. is too busy" I found this link http://msdn.microsoft.com/en-us/library/aa355056.aspx that says should not use using statement in typed proxies. Is that really true? I think I got a big code change (sigh). Is this problem comes only in typed proxies?

Sample code:

private ServiceClient proxy;

using(proxy = new ServiceClient("ConfigName", "http://serviceaddress//service.svc")){
    string result = proxy.Method();
}
VJAI
  • 32,167
  • 23
  • 102
  • 164
  • See also: http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue and also: http://stevesmithblog.com/blog/idisposable-and-wcf/ – marc_s Jul 18 '11 at 07:52
  • Interesting. I don't think you'll have issues if you use a binding such as basichttpbinding and create an instance on the server per call. – BennyM Jul 18 '11 at 07:54
  • @BennyM: the same problems will possibly occur, regardless of what binding you use ..... – marc_s Jul 18 '11 at 07:59

3 Answers3

20

The core of the problem is: at the end of your using block (which generally is a very good idea to have!), the WCF proxy will be disposed. However, during disposing of the WCF proxy, exceptions can occur - and those will cause the app to misbehave. Since this is done implicitly at the end of the using block, you might not even really see where the error occurs.

So typically, Microsoft recommends a pattern something like this:

private ServiceClient proxy;

try
{
    proxy = new ServiceClient("ConfigName", "http://serviceaddress//service.svc");
    string result = proxy.Method();
    proxy.Close();    
}
catch (CommunicationException e)
{
   // possibly log error, possibly clean up
   proxy.Abort();
}
catch (TimeoutException e)
{
   // possibly log error, possibly clean up
   proxy.Abort();
}
catch (Exception e)
{
   // possibly log error, possibly clean up
   proxy.Abort();
   throw;
}

You need to call the proxy.Close() method explicitly and be prepared to handle any exceptions that might occur from that call, too.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • I like to confirm one thing, if the Close() throw exceptions then the connections are left open so after a period the service can't able to serve new requests rgt? – VJAI Jul 18 '11 at 09:43
  • @Mark: unless you call `proxy.Abort()` after an exception happened - yes, then the proxy might linger around..... – marc_s Jul 18 '11 at 11:03
  • but isn't the same situation apply for any object that implement Idisposable ? – Stacker Jan 26 '16 at 18:42
2

Wrap the proxy operation and instantiation calls up in a class implementing IDisposable. When disposing, check the state property of the proxy and tidy up the channel before closing.

public void Dispose()
{
    if (this.MyProxy != null && this.MyProxy.State == CommunicationState.Faulted)
    {
        this.MyProxy.Abort();
        this.MyProxy.Close();
        this.MyProxy = null;
    }
    // ...more tidyup conditions here
} 
cspolton
  • 4,495
  • 4
  • 26
  • 34
HoganNZ
  • 61
  • 4
1

I like the approach from the comment from "Eric" on this blog (which is similar to another article: http://redcango.blogspot.com/2009/11/using-using-statement-with-wcf-proxy.htm):

"Personally, I like to create my own partial class for the client and override the Dispose() method. This allows me to use the ‘using’ block as I normally would.

public partial class SomeWCFServiceClient : IDisposable
{
  void IDisposable.Dispose()
  {
   if (this.State == CommunicationState.Faulted)
   {
    this.Abort();
   }
   else
   {
     this.Close();
   }
  }
}
AlignedDev
  • 8,102
  • 9
  • 56
  • 91