Welcome to EMC Consulting Blogs Sign in | Join | Help

Simon Evans' Blog

My blog covers the technology areas I focus on here at EMC Consulting, namely Architecture using the .NET Framework, ASP.NET, WCF, WCF Data Services and Windows Azure Follow me on twitter @simonevans

Guidelines for Consuming a Service Using a WCF Proxy

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.

Published 10 November 2008 23:04 by simon.evans

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

marcin.kaluza said:

Couple of points:

1) I could not agree more that it is absolutely imperative that channel has to be closed when the client is done with it. This issue may not demonstrate itself straight away but under heavy load the client will simply "hang" when there are too many proxies "hanging" around

2) There is no difference whatsoever between calling Close() and Dispose(). ClientBase<T>.Dispose() calls Close() so there is no difference between the two. (use reflector to see for yourself)

3) Because of 2 it is perfectly valid to use client proxies with "using" statement. As a matter of fact I used this approach when load testing easyjets.com service layer doing ca 1800 method call/sec

November 10, 2008 23:47
 

simon.evans said:

Hi Marcin

You are correct that Close and Dispose will call the same code, but it is the point at which the Dispose method (by a Using statement) gets called that can cause problems, because some unhandled exceptions can be swallowed. This is because you have torn down the managed code too quickly to catch all the exceptions from the channel stack.

November 11, 2008 09:41
 

Owain.Wragg said:

Simon,

In a scenario where you are waiting for the result of the service call is it still best to use the async methods

e.g.

               IAsyncResult asyncResult = myService.BeginDoStuff(request, null, null);

               result = myService.EndDoStuff(asyncResult);

Doesn't the thread block whilst waiting for the aysnc call to finish? So is this any better that just calling the synchronous DoStuff method?

November 11, 2008 11:03
 

simon.evans said:

Hi Owain

Whilst your code is running in the callback method, a thread is still being used, but the point is that when you make a synchronous request-reply call the thread is also blocked whilst the client and service endpoints are communicating with each other.

Blocked threads use up CPU time, and hence if you are concerned about CPU use on your client, or have a limited number of threads, then asynchronous calls are the answer. So, when your client is a server (for example you are making the call to the service from IIS), you should be particularly worried about this.

As an aside, Silverlight does not allow synchronous calls to services for exactly this reason; because there is a limit number of threads that Silverlight can execute.

November 11, 2008 11:34
 

curious said:

How does a blocked thread use CPU time?  Isn't the concept of thread blocking so that you do NOT use CPU time (ie. polling) while waiting on some IO or other 'event' to complete?  I was under the impression that the OS suspends (or does not schedule) the thread until the IO in question has completed, hence it does not use any cpu time.   Regardless of whether you use async or sync, the cpu is going to have to service the network stack as the reply packets come in, so that cpu time is the same regardless of the method used.

November 11, 2008 14:44
 

simon.evans said:

Hi curious

Blocking the thread itself does not use CPU time, but under load you will run out of available threads in the thread pool... at which point CPU time will be used queuing threads. The async pattern limits thread usage by removing blocked threads while the communication is being conducted.

November 12, 2008 14:08
 

marcin.kaluza said:

Hi Simon,

Async calls in WCF use threads from the thread pool, so a call to BeginXXX will use  one extra thread which will block waiting for response (J.Lowy, Programming WCF Services, p368).

If you are concerned about thread usage in the thread pool, async calls are not the way to go.

November 12, 2008 19:13
 

Andy said:

Does closing the proxy apply when you are caching your proxy?  If you close the proxy that you cached than the next time you attempt to pull it from the cache it will not be there.  

November 13, 2008 19:56
 

simon.evans said:

Hi Andy

When you close a proxy, the proxy remains instantiated... you just open it again. When close the proxy you are closing the communication over the channel stack, but the channel stack remains instantiated, so you can open communications again afterwards.

November 14, 2008 20:31
 

Andy said:

Why close the proxy if your caching it.  It makes it more tedious now because your wrapping every call in an open and close statement.

November 26, 2008 23:06
 

Reynold said:

Thanks for the blog entry, but I have a question regarding your reply to Andy on Nov. 14.  Do you actually have a tested and working sample of reopening a closed proxy?  I have the caching and such working, but when I try to reopen the proxy when it is in a closed state I get the following error message: "Cannot access a disposed object".

It seems like others have had similar issues (e.g. http://social.msdn.microsoft.com/forums/en-US/wcf/thread/23331256-c328-4ba5-8f03-9e8ee1a5fb8f/).

Do you have any ideas or suggestions?

December 2, 2008 23:35
 

simon.evans said:

Hi Reynold

This interesting... I've not actually seen that problem myself, but judging by the exception you are getting (and what the forums discuss), it looks to me like something higher up the stack is disposing of your proxy before you close it (like a using block). I'd suggest code profiling with DotTrace to help figure out where the disposal is happening.

Regards

Simon

December 16, 2008 13:10
 

Ruth said:

I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

Ruth

http://ramupgrade.info

March 18, 2009 07:18
 

espinete said:

Please, any sample source code ?? thanks

November 5, 2010 10:06

Leave a Comment

(required) 
(optional)
(required) 
Submit

About simon.evans

Simon is a Managing Consultant for Conchango in the UK, part of EMC Consulting Services. He is an expert in .NET development, and more specifically in WCF and ASP.NET, having participated in several Microsoft early adoption programs. Simon believes deeply that a broad understanding of key technology concepts is an essential foundation to being a gifted designer and builder of solutions.
Powered by Community Server (Personal Edition), by Telligent Systems