Problems with the Using Statement and WCF client
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 res开发者_如何学运维ult = proxy.Method();
}
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.
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
}
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();
}
}
}
精彩评论