Note – This post does not address duplex communications, it’s not in the scope of this post.
There are many approaches you might consider while using client proxies in your solution.
Some clients might instantiate a static proxy and use it throughout the entire application lifetime, some will instantiate a proxy per needed call, etc..
Let’s define “Sequential Execution Pattern” to help me around with the describing the basic principles.
A sequential execution, as implies, is a set of calls that are invoked one right after another. Meaning the calls are made sequentially.
Note it doesn’t have to be the same thread, It could be two asynchronous operations invoked in a sequential manner.
Plus, the calls are called right after another. (without waiting for a definite time / user initiated action)
Example for sequential execution:
MyServiceClient proxy= GetNewProxy();
try
{
proxy.Call1();
proxy.Call2();
proxy.Close();
}
catch { proxy.Abort(); }
Let’s get to it then..
1 - Using Using
You should not use the using directive while using proxies.
E.g.
using (MyServiceClient proxy= GetNewProxy()) { … }
The SDK comes with a sample showing exactly why you shouldn’t use it.
In essence, the dispose of the proxy calls the close which could yield an exception if the channel is faulted.
In such cases, your following code will not be executed and exceptions from inside the using statement can get masked.
The best practice of how to instantiate and dispose of the proxy is illustrated in the example above.
2 - Exceptions / Faults
If an exception is thrown out of the channel, you should dispose of the proxy and use a new one.
The channel could still be usable after exceptions, but that depends on the communication settings between the client and the server.
The best practice is to simply use a new proxy.
3 - One Way
One way operations should basically end the use of the client proxy.
Read more about it in my detailed post - WCF and OneWay – Behavioral Inconsistency
4 - Concurrent Environment
There may be cases where the client making calls to services lives in a concurrent environment – such as a Web Application or a Service itself which acts as a client.
In such cases, you should really follow the execution pattern principle – a proxy per sequential execution.
It was discovered that in a concurrent environment, it is best to use a different proxy for a sequential execution.
You should not make several calls on the same proxy at the same time – it is proven to be bad performance-wise and you don’t really get a self-contained execution. (A call can fault the channel, causing all the other operations on the same proxy fail as well)
5 - Asynchronous Invocation
There are two types of asynchronous invocations you can do on your proxy:
a. Invoke operations asynchronously in a sequential manner. (One after the the former is completed)
b. Invoke operations asynchronously in a concurrent manner. (Execute several operations on the same proxy at the same time – concurrently)
Sequential Manner – Not much problem there, you should use the same proxy (unless an exception occurred in the former call or was it one way)
Concurrent Manner – There lies a choice.
If you make many concurrent calls – as indicated in the “Concurrent Environment” principle – you should use a new proxy instance per invocation.
If you make real few – you have the choice, you can use the same proxy instance. I rather not since I prefer a self-contained behavior. (An exception in one asynchronous operation could fault the channel and fail all your other concurrent invocations)
Basically I would suggest using a proxy per asynchronous invocation for the sake of getting self-contained behavior plus ensuring good performance if the number of the concurrent calls increases.
A problem arises when the contract at hand is a sessionful one. In that case, if the session state matters you might have to invoke the concurrent asynchronous calls on the same proxy.
Summary – Determine Execution Pattern
To summarize all of the principles above, the main guidelines are -
You should use the same proxy instance for a sequential execution while one way and Exceptions should make you re-instantiate the proxy while taking asynchronous invocations principle into mind.
A little about Sessionful Contracts
When service is set as sessionful, it should indicate that the session matters (Otherwise, you should always prefer Per Call over Per Session).
That might make you wonder though – for example, perhaps you would have to use the same instance in a concurrent environment
However, when designing sessionful contracts, you should make the usage of the service available through a sequential execution pattern alone.
You wish to preserve some sort of scalability, plus, session is limited within a timeout.
That being said, All the principles above should adhere to sessionful contracts as well.
CodeProject