作者:榜榜爱打球 | 来源:互联网 | 2022-12-06 22:04
我们目前正在重构我们项目的各个部分上下异步,是的!
由于我们的理解不同,我和同事(让我们称他为吉姆)对于我们的异步/等待代码将如何执行以及编写它的方式有不同的看法.
以下是Jim写的示例方法:
public async Task GetHouseModel(Guid houseId)
{
House house = await _houseService.GetHouse(houseId);
Task> furniture = _furnitureService.GetFurnitureForHouse(house);
Task> appliances = _applianceService.GetAppliancesForHouse(house);
return _houseModelFactory.MakeHouseModel(await furniture, await appliances);
}
以及如何编写它的示例:
public async Task GetHouseModel(Guid houseId)
{
House house = await _houseService.GetHouse(houseId);
IEnumerable furniture = await _furnitureService.GetFurnitureForHouse(house);
IEnumerable appliances = await _applianceService.GetAppliancesForHouse(house);
return _houseModelFactory.MakeHouseModel(furniture, appliances);
}
我的理解是:因为上面的服务furniture
和appliance
服务中的方法都需要House
,所以House
在继续之前它们会等待可用.然后,两个需要的方法House
都会运行,但第二个方法(GetAppliancesForHouse
)不会等到第一个方法在开始之前完成.
吉姆的理解是:我们应该只在需要时才等待这两种方法.这样他们就会彼此平行.他认为按照我的方式做,将导致第二种方法等待第一种方法,即:GetAppliancesForHouse
等待GetFurnitureForHouse
.
这些理解中的任何一个是否正确?或者我们一直在进行弥补?我们何时应该等待?
1> Erndob..:
我的理解是:因为上述家具和家电服务的方法都要求House,他们会等待House继续使用.
你的理解是错误的.需要House的方法,他们不等你拿到House因为你需要它.他们不解决他们的依赖关系以及何时等待代码或不自己.代码等待获得Houses,因为你有await
它.它不知道接下来会发生什么.
然后,两个需要House的方法都会运行,但第二个方法(GetAppliancesForHouse)不会在开始之前等待第一个方法完成.
类似地,GetAppliancesForHouse
如果它应该等待或不基于依赖性,它将不会有自己的理解.GetAppliancesForHouse
将无法运行,因为您的代码GetFurnitureForHouse
首先要等待它.您的代码将始终按顺序运行.
吉姆的理解是:我们应该只在需要时才等待这两种方法.这样他们就会彼此平行.
这通常是正确的.正如其他人所指出的那样,代码仍然可能并不依赖于其他因素.此外,可能有合理的理由不希望并行运行代码.
他认为按照我的方式进行操作将导致第二种方法等待第一种方法,即:GetAppliancesForHouse等待GetFurnitureForHouse.
他是对的.
要查看确切的结果,您可以放置断点并查看每行后发生的情况.在Jims案例中,从家具到家用电器之后,家具变量还没有价值,它仍然是一项任务,但你已经在下一行了.
根据你的情况,去家电系列,你会看到家具已经有了价值,因为它等待它.
@AdamSimon总是要考虑潜在的线程问题,这就是理解async/await如何工作的重要原因.
@CamiloTerevinto是对的.另外,我要指出**Jim的方式可能会引入线程问题**.例如,如果EF用于数据访问并且*_applianceService*和*_furnitureService*共享相同的DbContext实例,则会出现问题,因为[DbContext不是线程安全的](/sf/ask/17360801/ -dbcontext线程安全的).
2> SO used to b..:
无论你是正确的,看到答案由@erndob的原因.但是,其中一个问题没有得到解答:
我们何时应该等待?
你想要按顺序完成工作吗?用你的方式.
你想要并行完成工作吗?用吉姆的方式.
注:吉姆的方式实际上并不会以并行方式运行,如果任务计划程序使用的是不能在同一时间运行两个任务,例如,由于缺乏系统资源(感谢@AdamSimon).