-2

I'm new to async / await, and have been trying to implement it in my 4.6 web api 2 project.

public class MyController : ApiController
{
     public async Task<Thing> Search(String searchTerms)
{
    myThing = new Thing();
    myThing.FirstProperty = await doFirstPropertyAsync(searchTerms);
    myThing.SecondProperty = await doSecondPropertyAsync(searchTerms);

 return myThing;

}
}

Basically I'm returning a class (Thing) that has two properties that take a few seconds each to populate. I'm actually loading maybe ~10 properties, but it's the same logic for all of them.

    public async Task<MyCoolSubObject> doFirstPropertyAsync(string searchTerms)
    {
        SomeController sController = new SomeController();
        Debug.WriteLine("first - starting.");

        var x = await Task.Run(()=>sController.Lookup(searchTerms));

        Debug.WriteLine("first - finishing.");
        return x;
    }

    public async Task<MyCoolSubObject> doSecondPropertyAsync(string searchTerms)
    {
        SomeOtherController sController = new SomeOtherController();
        Debug.WriteLine("second - starting.");

        var x = await Task.Run(()=>sController.Lookup(searchTerms));

        Debug.WriteLine("second - finishing.");
        return x;
    }

What's got my scratching my head:

When I look at the debug outputs, the first property assignment method call starts and finishes before the second completes. Again, I actually have like ten of these and no matter what order I put the property assignments in they complete in a serial fashion (ie: nothing starts until another one finishes).

These property assignments under the hood are basically doing database calls that take a while, hence I wanted them running in parallel if possible. The methods themselves ( SomeController.Lookup(string) ) contain no await/async/task stuff.

Eric
  • 2,273
  • 2
  • 29
  • 44
  • *"When I look at the debug outputs, the first property assignment method call starts and finishes before the second completes"* that sounds accurate. If you wanted these to run in parallel, async/await probably wouldn't be the right tool. Promise.all() would be more useful. – Kevin B Jul 07 '17 at 21:57
  • 1
    Possible duplicate of [Call async/await functions in parallel](https://stackoverflow.com/questions/35612428/call-async-await-functions-in-parallel) – Kevin B Jul 07 '17 at 22:00
  • It's running *serially* (one statement followed by another), not "synchronously" (blocking a thread). This is what `await` does; to do multiple asynchronous operations concurrently, use `Task.WhenAll`. Also, you shouldn't be using `Task.Run` on ASP.NET - this kind of async-over-sync defeats the purpose of asynchronous code in the first place. – Stephen Cleary Jul 08 '17 at 01:53

1 Answers1

1

Again, I actually have like ten of these and no matter what order I put the property assignments in they complete in a serial fashion (ie: nothing starts until another one finishes).

This happens because in your code you use the await keyword as soon as you kickoff the task, by doing that you prevent the method to continue to execute the next statement before the task will be done.

If you want to run your tasks in parallel you should kickoff all of them and only then await all of them using Task.WhenAll:

public async Task<Thing> Search(String searchTerms)
{
    myThing = new Thing();
    var firstTask = doFirstPropertyAsync(searchTerms);
    var secondTask = doSecondPropertyAsync(searchTerms);
    await Task.WhenAll(firstTask, secondTask);
    myThing.FirstProperty = await firstTask;
    myThing.SecondProperty = await secondTask;
    return myThing;
}

Note that when we await every task separately after we await Task.WhenAll the tasks have already been done, we do that in order to get the result from the task, although we can use the Result property (it will not block since we know the task has already been done) I prefer to use await for consistency reasons.

YuvShap
  • 3,825
  • 2
  • 10
  • 24