WCF asynchronous client proxy and asynchronous service operations

In this post, we will cover asynchronous operations with our WCF proxy and our WCF service.
All by all, this is not any rocket science, but in my attempt to master WCF basics it is one of the topics I will cover.

As usual, we start with a basic solution setup:

WCF Asynchrony solution overview

WCF.Asynchrony.Client: Console application used as client
WCF.Asynchrony.Service: WCF Service application with 1 WCF service named “Public”

Service interface:

WCF Service interface

Service implementation:

WCF Service Implementation

Our configuration:

WCF Service configuration

And we host this thing in our local IIS:

IIS hosted WCF service

1. Invoke service operations asynchronously from the client

We will start by attempting to invoke our service operation “InvokeOperation” asynchronously from our client console application.

We add a Service Reference at our client console application:

WCF Add Service Reference

Before adding the service reference, press Advanced:
Check the Generate asynchronous operations. By default when adding a service reference, operations are only added synchronously.

Generate asynchronous WCF operations client

Add the service reference with asynchronous operations. Now when creating a new proxy you will have access to the methods BeginInvokeOperation, EndInvokeOperation and InvokeOperationAsync, while before you only had the InvokeOperation method.

Our client console application code looks as following:

WCF asynchronous operation client

When running the asynchronous WCF client console application:

WCF async client

Not that difficult, using the BeginOperation and EndOperation methods.
The BeginInvokeOperation method takes the parameter (string), the asynchronous callback (in our case called AsynCallback) and the state object, in our case we just pass on the proxy.
The asynchronous callback method AsyncCallback, just gets the proxy out of the IAsyncResult.AsyncState again and we invoke the EndInvokeOperation on the proxy with as parameter the IAsyncResult. The EndInvokeOperation returns the result of our operation.
However there is still another solution, with the OperationAsync:

WCF Client Asynchronous operation Async

Before we invoke the InvokeOperationAsync, we defined which operation will handle the callback of the asynchronous operation, by InvokeOperationCompleted.
At the callback we can just get the result from this e.Result.
The async method above is less difficult then the Begin/End combination as you don’t need to work with the IAsyncResult and any AsyncState object.

Running the client console application:

WCF async client async callback
And for the people familiar with lambda expressions, you could also write the InvokeOperationAsync code as following:

Asynchronous WCF client with lambda expression

That way you do not longer have to create a separate function for the callback when the asynchronous operation completes.
Note: Asynchronous client operations are not possible if you work with channelFactory<>

2. Have your service operations work asynchronously, independent from whether the client calls it synchronously or asynchronously

We created a client console, which calls a WCF service operation asynchronously. This asynchrony is at the client side, freeing the primary thread during which the asynchronous operation is executing, making it able to execute other stuff, instead of being blocked by the processing of what the asynchronous operation does now. However this does not mean our WCF service is handling the request asynchronous. Our WCF service is still handling the incoming request synchronously. If our InvokeOperation method on our WCF Service would process some heavy I/O operations for example, it could be a large improvement for our service to handle the requests asynchronously, as the I/O operation would block our service thread.

To make our InvokeOperation method asynchronously on our service, our service interface should look like this:

WCF Service Asynchronous operation asyncpattern Begin End

Our InvokeOperation has to be split out in 2 parts: BeginInvokeOperation and EndInvokeOperation. So it turns your synchronous operation name to Begin+operation and End+operation.

Also the BeginMethod has to be signed with the [OperationContract(AsyncPattern=true)], while the EndMethod does not have to be marked at all.
The BeginMethod will return an IAsyncResult and the EndMethod will return the data structure our operation would have returned. The EndMethod also accepts as parameter an IAsyncResult, just as a default asynchronous EndOperation.

The above Begin/End combination should look familiar to the Begin/End operation we used at the client side to call an operation asynchronously.

Our asynchronous service implementation:

Asynchronous WCF service operation

Func<string,string> invokeOperation = a delegate called invokeOperation that takes a string as parameter and returns as string as result
So basically we create a delegate that contains the behavior of our InvokeOperation as if it would be invoked synchronously.

The func is a shortened lambda function equalling:

            Func<string, string> invokeOperation = (parametervalue) =>
                                                       {
                                                           return string.Format("Invoked with {0}", parametervalue);
                                                       };

After we created the delegate, we invoke it by the BeginInvoke, which is the same as the default asynchronous begin/end operations again, passing the parameters, the asynchronous callback and the state object.

At the EndInvokeOperation we cast the IAsyncResult to an AsyncResult, so we have access to the AsyncDelegate. We get the AsyncDelegate and call the EndInvoke, just as a default asynchronous EndOperation which takes the IAsyncResult as parameter. The EndInvoke operation returns the result of the operation.

Let’s adapt our client application again and test if our asynchronous service operation is working.
Let’s start by Configuring our Service Reference at our client console application

Configure service reference

And disable the “Generate Asynchronous Operations” and update the service reference:

WCF client generate asynchronous operations

When you now try to call the InvokeOperation on the proxy, you will notice that is 1 operation present named InvokeOperation:

WCF asynchronous service

So even though at our service our operation is with Begin/End, at the client it only shows as 1 single operation. So the client has no way of knowing whether the operation at the service is executed synchronously or asynchronously. The client does not have to know either, since the client behavior is independent of the service behavior.

Our client console application code:

WCF Client and service asynchrony

And when executing the console:

Asynchronous WCF operation

For the client the invocation of the operation is synchronously, though the service is handling the processing of the request asynchronously.
If we set the “Generate Asynchronous Operations” at our client proxy check again, we would also be able to call the service operation asynchronously from the client. In that case, both the client and the service would handle the operation asynchronously.

Any suggestions, remarks or improvements are always welcome.
If you found this information useful, make sure to support me by leaving a comment.

Cheers and have fun,

Robbin

Advertisements