understanding - task whenall c#
¿Cuándo debería esperar a mis asyncs? (2)
Actualmente, estamos refacturando secciones de nuestro proyecto para que sean asincrónicas, ¡sí!
Debido a nuestra diferente comprensión, yo y un colega (llamémosle Jim) tenemos opiniones diferentes sobre cómo se ejecutará nuestro código async / await y sobre la forma de escribirlo.
Este es el método de ejemplo que Jim escribió:
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);
}
Y el ejemplo de cómo lo escribiría:
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);
}
Según tengo entendido, debido a que los métodos tanto en los servicios de furniture
y appliance
House
en los de arriba requieren House
, esperarán a que House
esté disponible antes de continuar. Luego, se ejecutarán ambos métodos que necesiten House
, pero el segundo método ( GetAppliancesForHouse
) no esperará a que el primero termine antes de comenzar.
La comprensión de Jim es: que debemos esperar ambos métodos solo cuando se necesiten. Para que ambos corran en paralelo el uno al otro. Él piensa que hacerlo a mi manera dará como resultado que el segundo método espere el primero, es decir: GetAppliancesForHouse
esperando GetFurnitureForHouse
.
¿Alguno de estos entendimientos es correcto? ¿O acabamos de inventarnos a medida que avanzamos? ¿Cuándo deberíamos esperar?
Según tengo entendido, debido a que los métodos tanto en los servicios de muebles y electrodomésticos de House como en los de arriba requieren House, esperarán a que House esté disponible antes de continuar.
Tu comprensión es incorrecta. Los métodos que requieren House, no están esperando que consigas House porque lo necesites. No resuelven sus dependencias y cuándo esperar el código o no por su cuenta. El código espera para obtener Casas porque has await
antes . No está al tanto de lo que sucederá después.
Luego, se ejecutarán ambos métodos que necesiten House, pero el segundo método (GetAppliancesForHouse) no esperará a que el primero termine antes de comenzar.
Del mismo modo, GetAppliancesForHouse
no tendrá su propio entendimiento si debe esperar o no en función de las dependencias. GetAppliancesForHouse
no se ejecutará, porque su código dice que aguarde GetFurnitureForHouse
antes que primero. Tu código siempre se ejecutará secuencialmente .
La comprensión de Jim es: que debemos esperar ambos métodos solo cuando se necesiten. Para que ambos corran en paralelo el uno al otro.
Eso es generalmente cierto. Como otros han señalado, el código aún podría ejecutarse no en paralelo dependiendo de otros factores. Además, puede haber razones legítimas para no querer ejecutar el código en paralelo.
Él piensa que hacerlo a mi manera dará como resultado que el segundo método espere el primero, es decir: GetAppliancesForHouse esperando GetFurnitureForHouse.
El tiene razón.
Para ver qué sucede exactamente, puedes poner puntos de corte y ver qué ocurre después de cada línea. En el caso de Jims, después de pasar de Muebles a Electrodomésticos, la variable de mobiliario aún no tendrá valor, sigue siendo una tarea, pero ya se encuentra en la siguiente línea.
Con su caso, yendo a la línea de Electrodomésticos, verá que Furniture ya tiene el valor, ya que lo esperó.
Ninguno de ustedes está en lo correcto, vea la respuesta de Erndob por las razones. Sin embargo, una de las preguntas no es respondida:
¿Cuándo deberíamos esperar?
- ¿Quieres que el trabajo se haga de forma secuencial? Usa tu camino.
- ¿Quieres que el trabajo se haga en paralelo? Usa el camino de Jim.
Nota : la forma de Jim no se ejecutará en paralelo si el Programador de tareas utilizado no puede ejecutar ambas tareas al mismo tiempo, por ejemplo, debido a la falta de recursos del sistema (gracias @AdamSimon ).