0

I just want everyones feedback about the following Async Controller using the Web Api HttpClient. This looks very messy is there a way to make it cleaner? Does anyone have a good wrapper around chaining multiple async tasks together?

public class HomeController : AsyncController
{
    public void IndexAsync()
    {
        var uri = "http://localhost:3018/service";
        var httpClient = new HttpClient(uri);

        AsyncManager.OutstandingOperations.Increment(2);
        httpClient.GetAsync(uri).ContinueWith(r =>
        {
            r.Result.Content.ReadAsAsync<List<string>>().ContinueWith(b =>
            {
                AsyncManager.Parameters["items"] = b.Result;
                AsyncManager.OutstandingOperations.Decrement();
            });
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    public ActionResult IndexCompleted(List<string> items)
    {
        return View(items);
    }
}
Chris Kolenko
  • 1,020
  • 17
  • 32

2 Answers2

0

You seem to be using a bit to many async calls and AsyncManager.OutstandingOperations.Decrement(). The following code is enough to load the Flickr photo information asynchronously using YQL.

public class HomeController : AsyncController
{
    public void IndexAsync()
    {
        var uri = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photos.recent";
        var httpClient = new HttpClient(uri);

        AsyncManager.OutstandingOperations.Increment();
        httpClient.GetAsync("").ContinueWith(r =>
            {
                var xml = XElement.Load(r.Result.Content.ContentReadStream);

                var owners = from el in xml.Descendants("photo")
                                select (string)el.Attribute("owner");

                AsyncManager.Parameters["owners"] = owners;
                AsyncManager.OutstandingOperations.Decrement();
            });
    }

    public ActionResult IndexCompleted(IEnumerable<string> owners)
    {
        return View(owners);
    }
}
Maurice
  • 27,582
  • 5
  • 49
  • 62
  • Hi Maurice, I understand my example seems very simplistic. But what happens if I do need to chain two long running processes together? I'm looking for a good way to abstract this out of my controller also. This code looks very ugly and hard to read. – Chris Kolenko Jul 14 '11 at 00:49
  • In case of chained async calls you stil only need a single AsyncManager.OutstandingOperations.Decrement() in the last part of the chain. I know not a big difference :-( Other than that at the moment there are the standard options of using functions instead of lambda expressions. With the C# 5 await this should become a lot easier to read/write. – Maurice Jul 14 '11 at 07:10
0

You may take a look at http://pfelix.wordpress.com/2011/08/05/wcf-web-api-handling-requests-asynchronously/.

It contains an example based on the task iterator technique ( http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx ) for chaining async operations.

Pedro Felix
  • 1,056
  • 1
  • 8
  • 12