I am trying to make a WCF REST method entirely asynchronous (I don’t want to block anywhere). Essentially I have a simple service with 3 layers: Service, Business Logic and Data Access Layer. The Data Access Layer is accessing a database and it can take several second to get a response back from that method.
I don’t understand very well how to chaining of all those method work. Can someone please help me to complete the sample I am trying to write below? I don’t understand well the pattern used by WCF and I didn’t find much documentation on the subject.
Can someone help me to complete the following example? In addition, how can I measure that the service will be able to handle more load than a typical synchronous implementation?
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Threading.Tasks;
namespace WcfRestService1
{
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Service1
{
private BusinessLogic bll = new BusinessLogic();
// Synchronous version
[WebGet(UriTemplate = "/sync")]
public string GetSamples()
{
return bll.ComputeData();
}
// Asynchronous version - Begin
[WebGet(UriTemplate = "/async")]
[OperationContract(AsyncPattern = true)]
public IAsyncResult BeginGetSampleAsync(AsyncCallback callback,
object state)
{
Task<string> t = bll.ComputeDataAsync();
// What am I suppose to return here
// return t.AsyncState; ???
}
// Asynchronous version - End
public List<SampleItem> EndGetSampleAsync(IAsyncResult result)
{
// How do I handle the callback here?
}
}
public class BusinessLogic
{
public Task<string> ComputeDataAsync()
{
DataAccessLayer dal = new DataAccessLayer();
return dal.GetData();
}
public string ComputeData()
{
Task<string> t = this.ComputeDataAsync();
// I am blocking... Waiting for the data
t.Wait();
return t.Result;
}
}
public class DataAccessLayer
{
public Task<string> GetData()
{
// Read data from disk or network or db
}
}
}
Here’s an example. I got it working with help from the following posts:
Edit: Added an example of an async client
Implement Classic Async Pattern using TPL
http://pfelix.wordpress.com/2008/06/27/wcf-and-the-asyncpattern-property-part-1/
http://pfelix.wordpress.com/2008/06/28/wcf-and-the-asyncpattern-part-2/
Here’s a little do-nothing service:
And here’s the client (command line):
if you put trace points on the service, you can see that WCF really is calling EndOperation for you.
Async Client Example
First, you will need to generate an async proxy. You can do that by right-clicking on the Service Reference (in the References Folder of your project), and choosing “Configure Service Reference”. Check the “Generate Asynchronous Operations” checkbox.
Now your client proxy will have some new members that weren’t there before. Here’s how to use them: