#c# #asp.net-web-api #async-await
#c# #asp.net-web-api #async-ожидание
Вопрос:
У меня есть несколько async
методов, которые возвращают один и тот же тип из разных вызовов REST Api на основе OAuth.
Если я вызову его напрямую, я смогу получить данные обратно:
//Call a specific provider
public async Task<List<Contacts>> Get()
{
return await Providers.SpecificProvider.GetContacts();
}
Однако, если я попытаюсь перебрать несколько учетных записей, объект возвращается до AWAIT
завершения:
//Call all providers
public async Task<List<Contacts>> Get()
{
return await Providers.GetContactsFromAllProviders();
}
public async Task<List<Contacts>> GetContactsFromAllProviders()
{
var returnList = new List<Contacts>();
//Providers inherits from List<>, so it can be enumerated to trigger
//all objects in the collection
foreach (var provider in Providers)
{
var con = await provider.GetContacts();
returnList.Add(con);
}
return returnList;
}
Я новичок async
и, вероятно, упускаю что-то простое
Комментарии:
1. Другая ситуация. У него уже есть решение для другого типа цикла, и он ищет эффективность.
2.
async
Ключевое слово в первом методе является избыточным. Вы можете простоreturn Providers.SpecificProvider.GetContacts();
Ответ №1:
Предоставленный вами код будет последовательно вызывать веб-службу для каждого поставщика по очереди. Я не понимаю, как ваше утверждение, которое объект возвращает до завершения ожидания, может быть истинным, потому что внутри цикла ожидается вызов GetContacts
.
Однако вместо последовательного вызова поставщиков вы можете вызывать их параллельно, что в большинстве случаев должно сократить время выполнения:
var tasks = providers.Select(provider => provider.GetContacts());
// Tasks execute in parallel - wait for them all to complete.
var result = await Task.WhenAll(tasks);
// Combine the returned lists into a single list.
var returnList = result.SelectMany(contacts => contacts).ToList();
Комментарии:
1.
returnList.Add
вызывается, но список возвращаемых данных уже был возвращен до того, как в него были добавлены все элементы.2.
await Task.WhenAll(tasks)
было бы более эффективно, верно?3. @MattJohnson: Да, вы правы. Я соответствующим образом обновил код.
4. @Wesley, возвращается задача, которая после завершения будет иметь
returnList
.