我什么时候应该等待异步?

时间:2018-08-22 12:07:21

标签: c# .net async-await

我们当前正在重构项目的各个部分,以便上下同步,是的!

由于我们的理解不同,我和一位同事(我们叫他吉姆)对我们的异步/等待代码将如何执行以及编写方式有不同的看法。

这是吉姆写的示例方法:

public async Task<HouseModel> GetHouseModel(Guid houseId)
{
    House house = await _houseService.GetHouse(houseId);

    Task<IEnumerable<Furniture>> furniture = _furnitureService.GetFurnitureForHouse(house);

    Task<IEnumerable<Appliances>> appliances = _applianceService.GetAppliancesForHouse(house);

    return _houseModelFactory.MakeHouseModel(await furniture, await appliances);
}

以及如何编写示例:

public async Task<HouseModel> GetHouseModel(Guid houseId)
{
    House house = await _houseService.GetHouse(houseId);

    IEnumerable<Furniture> furniture = await _furnitureService.GetFurnitureForHouse(house);

    IEnumerable<Appliances> appliances = await _applianceService.GetAppliancesForHouse(house);

    return _houseModelFactory.MakeHouseModel(furniture, appliances);
}

我的理解是:由于上述furnitureappliance服务中的方法都需要House,因此它们将等待House可用,然后再继续。然后,需要使用House的两个方法都将运行,但是第二个方法(GetAppliancesForHouse)不会等待第一个方法完成才开始。

Jim的理解是:只有在需要这两种方法时,我们才应该等待它们。这样它们将彼此平行运行。他认为,以我的方式进行操作将导致第二种方法等待第一种方法,即:GetAppliancesForHouse等待GetFurnitureForHouse

这些理解是否正确?还是我们一直在进行弥补?我们什么时候应该等待?

2 个答案:

答案 0 :(得分:49)

  

我的理解是:由于上述家具和家电服务中的方法都需要House,因此他们将等待House可用后再继续。

您的理解是错误的。需要众议院的方法,他们不是在等待您获得众议院,因为您需要它。他们不解决自己的依赖关系以及何时等待代码或不等待代码。 代码等待获得房屋,因为您之前有await 。它不知道接下来会发生什么。

  

然后,需要House的两个方法都将运行,但是第二个方法(GetAppliancesForHouse)将在启动之前不等待第一个方法完成。

类似地,GetAppliancesForHouse对于是否应该依赖于依赖项也不会有自己的了解。 GetAppliancesForHouse无法运行,因为您的代码要求先等待GetFurnitureForHouse您的代码将始终按顺序运行

  

Jim的理解是:只有在需要这两种方法时,我们才应该等待它们。这样它们将彼此平行运行。

通常是这样。正如其他人指出的那样,取决于其他因素,该代码可能仍不能并行运行。另外,可能有正当的理由不想并行运行代码。

  

他认为按照我的方式进行操作会导致第二种方法等待第一种方法,即:GetAppliancesForHouse等待GetFurnitureForHouse。

他是对的。

要查看确切发生了什么,可以放置断点并查看每行之后发生的情况。 在吉姆斯的情况下,从“家具”到“家电”之后,家具变量尚无价值,这仍然是一项任务,但是您已经在下一行了。

在您的案例中,转到“设备”行,您将看到家具已经具有该值,因为它在等待它。

答案 1 :(得分:8)

你们俩都不正确,请参阅the answer@erndob,以了解原因。但是,未回答其中一个问题:

  

我们什么时候应该等待?

  • 您要按顺序完成工作吗?用你的方式。
  • 您是否希望并行进行这项工作?用吉姆的方式。

注意:如果使用的任务计划程序无法同时运行两个任务,例如,由于缺少系统资源,Jim的方法实际上不会并行运行(感谢{{3 }}。