WCF: dispose/close proxies without the using statement

If you work with WCF, you should never forget to Close or Dispose your proxies when you do not need them anymore, because otherwise you might keep unmanaged resources (ports, channels, whatever) allocated. This does not sound too interesting or unusual yet, as we have all come across disposable objects before. In a particular project, I used “using statements” as usual, since the proxies implemented the IDisposable interface.
But the following issue surprised me in my current project: you should NOT use the “using” statement to ensure the proxy is disposed. In a nutshell, the reason is that the Close method tries to close the communication in a “nice way”, and this sometimes requires further communication or other complex activities. Unfortunately, this operation can throw exceptions, and it does not matter whether you called Dispose or Close to initiate the closing operation.
If you think about what the using statement means (the Dispose is executed in the “finally”), it is only a good pattern when Dispose works “safely”, so it does not throw exceptions when you want to get rid of the object already anyway. If there is a chance of an exception occurring during Dispose, you might run into trouble with this approach, e.g. a “real” exception from the body of the using statement may get hidden by an uninteresting exception that just informs you that you cannot close the communication nicely.
 The C# “using” statement results in a call to Dispose(). This is the same as Close(), which may throw exceptions when a network error occurs. Because the call to Dispose() happens implicitly at the closing brace of the “using” block, this source of exceptions is likely to go unnoticed both by people writing the code and reading the code. This represents a potential source of application errors.

The first problem illustrated, is that the closing brace throws an exception and the code after the closing brace does not execute:
using (CalculatorClient client = new CalculatorClient())
{

} // <– this line might throw
Console.WriteLine(“Hope this code wasn’t important, because it might not happen.“);

Even if nothing inside the using block throws an exception or all exceptions inside the using block are caught, the Console.Writeline might not happen because the implicit Dispose() call at the closing brace might throw an exception.

The second problem illustrated  is another implication of the closing brace throwing an exception:

using (CalculatorClient client = new CalculatorClient()){

throw new ApplicationException(“Hope this exception was not important, because “+
it might be masked by the Close exception.“);
} // <– this line might throw an exception.

Because the Dispose() occurs inside a “finally” block, the ApplicationException is never seen outside the using block if the Dispose() fails. If the code outside must know about when the ApplicationException occurs, the “using” construct may cause problems by masking this exception. Finally, the sample demonstrates how to clean up correctly when exceptions occur. This uses a try/catch block to report errors and call Abort.

try{
    ...
    client.Close();
}
catch (CommunicationException e){
    ...
    client.Abort();
}catch (TimeoutException e){
    ...
    client.Abort();
}
catch (Exception e){
    ...
    client.Abort();
    throw;
}

The using statement and ServiceHost: Many self-hosting applications do little more than host a service, and ServiceHost.Close rarely throws an exception, so such applications can safely use the using statement with ServiceHost. However, be aware that ServiceHost.Close can throw a CommunicationException, so if your application continues after closing the ServiceHost, you should avoid the using statement and follow the pattern previously given.

(sursa: http://blog.genom-e.com/PermaLink,guid,b9e3019d-0d68-4344-9c7a-407774323d0f.aspx,

http://msdn.microsoft.com/en-us/library/aa355056.aspx)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s