Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / WCF

Don't Use 'using()' with a WCF Proxy

5.00/5 (1 vote)
21 Jan 2016CPOL 5.3K  
Don't use 'using()' with a WCF proxy

If you're trying to be a conscientious developer and making sure that you cleanup your resources - great! You are writing 'using()' blocks around all of your disposable items - great... except when the disposable item is a WCF Client/Proxy! The using() statement and the try/finally effectively have the same IL:

MSIL
// The IL for this block is effectively the same as
            // the IL for the second block below
            using (var win = new Form())
{
}

            // This is the second block
            Form f = null;
            try
{
    f = new Form();
}
            finally
{
            if (f != null)
    {
        f.Dispose();
    }
}

Here's the IL for the 'using()' block above compiled in Release mode:

MSIL
IL_0000:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()
IL_0005:  stloc.0
.try
{
    IL_0006:  leave.s    IL_0012
}  // end .try
finally
{
    IL_0008:  ldloc.0
    IL_0009:  brfalse.s  IL_0011
    IL_000b:  ldloc.0
    IL_000c:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_0011:  endfinally
}  // end handler

Here's the IL for the second block (try/finally) compiled in Release mode:

MSIL
IL_0012:  ldnull
IL_0013:  stloc.1
.try
{
    IL_0014:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()
    IL_0019:  stloc.1
    IL_001a:  leave.s    IL_0026
}  // end .try
finally
{
    IL_001c:  ldloc.1
    IL_001d:  brfalse.s  IL_0025
    IL_001f:  ldloc.1
    IL_0020:  callvirt   instance void [System]System.ComponentModel.Component::Dispose()
    IL_0025:  endfinally
}  // end handler

As you can see, the IL is nearly identical.

Well, this is all fine and good but let's get back to the issue with WCF. The problem is that if an exception is thrown during disposal of the WCF client/proxy, the channel is never closed. Now, in general, any exception that occurs during disposal of an object is indeed undesirable. But, in the case of WCF, multiple channels remaining open could easily cause your entire service to fall on its face - not to mention what might eventually happen to your web server.

Here is an alternative solution that can be used:

C#
WCFProxy variableName = null;
            try
{
    variableName = new WCFProxy();

            // TODO code here

    variableName.Close();
}
            // if you need to catch other exceptions, do so here...
            catch (Exception)
{
            if (variableName != null)
    {
        variableName.Abort();
    }
            throw;
}

MSDN does have a brief on this issue which you can read here.

License

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