Асинхронизация / ожидание в глубоко вложенной иерархии методов - PullRequest
0 голосов
/ 03 сентября 2018

Если вы хотите внедрить асинхронный метод в глубине иерархии вызовов, является ли наилучшей практикой (или наилучшей рекомендуемой практикой), чтобы сделать всех родителей асинхронными?

Я полностью понимаю, как поток управления движется в асинхронных методах, но большинство примеров в Интернете показывают только один метод. Меня интересует, как работать с async / await в глубоко вложенной иерархии вызовов.

Например, что произойдет, если у вас есть:

void ControllerMethod() // Root method
{
     ServiceA_MethodOne();
}

// In another place in code
void ServiceA_MethodOne() 
{
     ServiceB_MethodOne();
}

// In another place in code
async Task<List<Product>> ServiceB_MethodOne()
{
     var data = await ctx.Products.ToListAsync();
     // some code here works with data.
}

Похоже, что по сути, потому что вы хотели получать Products асинхронно в одном из ваших глубоко вложенных дочерних методов, все родительские методы теперь должны быть помечены как асинхронные (я специально не пометил родителей как асинхронных в приведенном выше примере) пример)

Это правильное предположение?

Теперь я знаю о GetAwaiter().GetResult(), который фактически может сделать это:

void ControllerMethod() // Root method
{
     ServiceA_MethodOne();
}

// In another place in code
void ServiceA_MethodOne() 
{
     ServiceB_MethodOne().GetAwaiter().GetResult();
}

// In another place in code
async Task<List<Product>> ServiceB_MethodOne()
{
     var data = await ctx.Products.ToListAsync();
     // some code here works with data.
}

Это был бы один из способов "инкапсулировать" асинхронность в один метод. Но во многих статьях / руководствах это нахмурилось (и за этим стоят действительные, но еще не понятые технические объяснения)

Итак, чтобы подвести итог вопроса в более общем виде: когда вы используете async / await для метода, вся ли иерархия ваших родительских вызовов, начиная с прямого родителя, который вызывает ваш метод, полностью переходит к корневому методу (вызывающему которого вы не иметь контроля над), быть реализованы как асинхронные методы?

1 Ответ

0 голосов
/ 03 сентября 2018

Правило большого пальца полностью асинхронно . Это не обязательно означает, что вам нужно использовать ключевое слово async. Вы также можете вернуть то же задание, которое получили.

void ControllerMethod() // Root method
{
     return ServiceA_MethodOne().GetAwaiter().GetResult();
}

// In another place in code
Task ServiceA_MethodOne() 
{
     return ServiceB_MethodOne();
}

// In another place in code
async Task<List<Product>> ServiceB_MethodOne()
{
     var data = await ctx.Products.ToListAsync();
     // some code here works with data.
}

Также важно попытаться сделать ваш корневой метод асинхронным, если это возможно. ASP.NET MVC поддерживает асинхронные действия. Если вы пишете консольное приложение и используете C # 7, вы также можете сделать свой метод Main асинхронным.

...