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);
    }
}
share|improve this question
Also looking at the await keyword if anyone has any advice – Chris Kolenko Jul 12 '11 at 15:29

2 Answers

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);
    }
}
share|improve this answer
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 0: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 7:10

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.