Tuesday, 30 October 2012

Calling WCF Services asynchronously using async and await

In my previous post, I covered how to use async and await keywords in C# 5 to create asynchronous methods. This post is a continuation of asynchronous programming, in which I will cover how to call WCF services from a client program using async and await.

Response of an application will be slower when it includes heavy weight operations like running complex queries against database, reading a piece of data from a file, calling a service to get some data or any remote operation. When such operations are performed synchronously, the application will be halted till the operation gets over. If we assign the slower operation to a separate task, the thread will be free to perform some other operation till the operation responds.

When a WCF service is called synchronously, the thread associated with the operation is idle till the response is obtained from the server. To avoid this in earlier versions of .NET framework (4.0 or earlier), we had an option to create asynchronous methods with an associated event. Using .NET 4.5, we can create task-based proxies while adding service reference to an application. This can be done using by clicking on the Advanced button in the Add Service Reference dialog.


Add Service Reference

On the Service Reference Settings dialog, check Allow Generation of asynchronous operations and Generate task-based operations.




Please note that this feature is available in .NET framework 4.5 onwards. i. e., to be able to generate task-based asynchronous proxies, target version of the project to which we are adding the service reference should be 4.5 or above.

For example, say a WCF service contains GetAllEmployees method, which returns a collection of Employees. Following snippet shows signature of the method:
List<Employee> GetAllEmployees();

If reference of this service is added to a client application written .NET 4.5 with task-based operations enabled, then you will be able to find the following two proxies in the generated Reference.cs file for the above method:
Public EmployeeServiceReference.Employee[] GetAllEmployees() {
    return base.Channel.GetAllEmployees();
}
        
public System.Threading.Tasks.Task<EmployeeServiceReference.Employee[]> GetAllEmployeesAsync() {
    return base.Channel.GetAllEmployeesAsync();
}

First proxy is the synchronous proxy and second one is the task-based proxy. We can call the WCF service asynchronously using the second proxy.

As we discussed in the previous post, any method that returns a Task can be called using await. In a client application, the method GetAllEmployeeAsync can be called using await keyword. Following is a sample method calling the service asynchronously:
async void LoadDataFromService()
{
    EmployeeServiceClient client = new EmployeeServiceClient();
    var getEmployeesTask = client.GetAllEmployeesAsync();
    Employees = await getEmployeesTask;
}

Happy coding!

2 comments:

  1. The last code snippet is really bad example. You should never use async void unless you are writing top level events. The method should return task instead of void, otherwise you will not know when the async method finishes. Also you are not able to handle exceptions thrown in async void methods.

    ReplyDelete
  2. Hey Chick, I agree to that. I didn't know that when I wrote this post nearly three years back. I know about the difficulties around async void functions. I will get it changes in some time.

    ReplyDelete