等待异步代码似乎仍在运行同步

时间:2017-07-07 15:25:59

标签: async-await asp.net-web-api2 task-parallel-library .net-4.6

我是async / await的新手,并且一直试图在我的4.6 web api 2项目中实现它。

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;

}
}

基本上我正在返回一个类(Thing),它有两个属性,每个属性需要几秒钟来填充。我实际上加载了大约10个属性,但它们都是相同的逻辑。

    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;
    }

让我挠头的是什么:

当我查看调试输出时,第一个属性赋值方法调用开始并在第二个完成之前完成。再一次,我实际上有十个这样的,无论我以什么顺序将属性赋值以连续的方式完成(即:在另一个完成之前没有任何内容开始)。

引擎盖下的这些属性分配基本上是在做一段时间的数据库调用,因此我希望它们尽可能并行运行。方法本身(SomeController.Lookup(string))不包含await / async / task东西。

1 个答案:

答案 0 :(得分:1)

  

同样,我实际上有十个这样的,不管我是什么顺序   将属性分配以连续方式完成(即:   没有什么可以开始,直到另一个完成。)

这是因为在您的代码中,一旦启动任务就会使用await关键字,这样做可以防止方法在任务完成之前继续执行下一个语句。

如果你想并行运行你的任务,你应该启动所有这些任务,然后使用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;
}

请注意,当我们等待Task.WhenAll任务已经完成后,我们单独等待每个任务时,我们这样做是为了从任务中获取结果,尽管我们可以使用Result属性(它不会阻止,因为我们知道任务已经完成了)我更倾向于使用await来保持一致性。