This is a blog I've been meaning to write for over a year now, but have just not had the time. Its as much a "note to self" as a blog for external consumption.
WCF provides the ability to generate a client proxy that communicates with a service, such as a SOAP service conforming to basic profile. Generating a proxy can be done by either using the SvcUtil.exe command from the Visual Studio command prompt, or by using the "Add Service Reference" feature of Visual Studio 2008 and pointing Visual Studio at the WSDL of your service. This action will generate a client proxy class and the required WCF client configuration file. You can write code against this client proxy class and armed with the client configuration, WCF will handle the communication to the service endpoint and the (de)serialization of messages into CLR types.
When a client proxy class is instantiated, WCF will build a channel stack based on the binding settings contained in the client configuration. This binding includes the address of the service, the transport to use, the encoding of the message and any service policies that apply to the service endpoint. The channel stack is the runtime representation of the way in which the WCF client will communicate with the service. For example, an average SOAP based service will communicate using an HTTP transport using a text encoding, and the service may apply additional WS-* policies such as WS-Security to implement service authentication.
Much of what I have just written is common knowledge, but much less written about the performance implications of how best to use a generated WCF client proxy. There are a few really important points to note when using these generated classes, and how this affects the performance of your application:
Consider caching the proxy object
When you instantiate a proxy class, WCF examines the binding configuration and uses reflection to generate the channel stack at runtime. This channel is fairly intensive to create, and thus creating the client proxy class every time you make a call to a service operation is excessively expensive. Thus, you should consider caching the proxy object, or hold the proxy object in a static variable. For a web site the most logical place to cache the proxy is using System.Web.Caching. You need to be aware that you can only reuse the same proxy when the channel stack is exactly the same, and this means running in the same security context (for example you might need to cache by username if you are using Windows impersonation).
Consider calling request-reply service operations asynchronously
For a request-reply calls to a service you should consider calling the asynchronous BeginMyOperation() method rather than the synchronous MyOperation(). This is because when a synchronous call to a service operation is made, the thread is blocked until the reply is received. This causes the CPU to work much harder than if you use asynchronous calls and deal with the response in a callback.
Always call the Close() method on the proxy object
The WCF client proxy contains a method named Close() which you should call after you have completed communications with the service endpoint. This method closes communications over the channel stack and disposes of any unmanaged resources. Failure to call this method will seriously degrade the performance of your client application, as communications are not properly closed and unmanaged resources may consume excess memory.
Do not instantiate the client in a Using statement, or call the Dispose() method
Calling the dispose method can lead to some communication exceptions being hidden (because the unmanaged resources are disposed too quickly). It is also unnecessary to call Dispose() when you call the Close() method, because this method handles disposal of resources for you.