У меня есть следующая операция в созданном мной веб-API:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}
Вызов этого веб-сервиса выполняется через вызов JQuery Ajax следующим образом:
$.ajax({
url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
type: "GET",
dataType: "json",
success: function (result) {
vm.items([]);
var data = result.Products;
vm.totalUnits(result.TotalUnits);
}
});
Я видел, как некоторые разработчики реализуют предыдущую операцию таким образом:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}
Однако следует сказать, что GetProductsWithHistory () - довольно долгая операция. Какую пользу мне принесет асинхронная работа webAPI с учетом моей проблемы и контекста?
c#
jquery
ajax
asp.net-web-api
async-await
Давид Хименес Мартинес
источник
источник
async Task<T>
. Помните, AJAX был реализован еще до того, как TPL вообще существовала :)GetProductsWithHistoryAsync()
возвратеTask<CartTotalsDTO>
. Написание асинхронного режима вашего контроллера может оказаться полезным, если вы намереваетесь также перенести выполняемые им вызовы в асинхронные; тогда вы начнете получать выгоду от асинхронных частей по мере переноса остальных.Ответы:
В вашем конкретном примере операция не является асинхронной, поэтому вы делаете асинхронную синхронизацию. Вы просто освобождаете один поток и блокируете другой. Для этого нет причин, потому что все потоки являются потоками пула потоков (в отличие от приложения с графическим интерфейсом).
От Должен ли я предоставлять синхронные оболочки для асинхронных методов?
Однако при выполнении вызовов WebAPI,
async
когда выполняется фактическая асинхронная операция (обычно ввод-вывод), вместо блокировки потока, который сидит и ожидает результата, поток возвращается в пул потоков и, таким образом, может выполнять некоторые другие операции. В целом это означает, что ваше приложение может делать больше с меньшими ресурсами, что улучшает масштабируемость.источник
await Task.Run(() => CPUIntensive())
) бесполезен в asp.net. Вы ничего не получите от этого. Вы просто освобождаете один поток ThreadPool, чтобы он занимал другой. Это менее эффективно, чем простой вызов синхронного метода.await Task.WhenAll
для параллельного выполнения.Task.Run
если хотите распараллелить нагрузку на несколько потоков, но это не то, что означает «асинхронность поверх синхронизации». "async over sync" - ссылки на создание асинхронного метода в качестве оболочки над синхронным. Вы можете увидеть в цитате моего ответа.Одним из подходов может быть (я успешно использовал это в клиентских приложениях), чтобы служба Windows выполняла длительные операции с рабочими потоками, а затем делала это в IIS, чтобы освободить потоки до тех пор, пока операция блокировки не будет завершена: Обратите внимание, это предполагает результаты сохраняются в таблице (строки, идентифицируемые с помощью jobId), и более чистый процесс очищает их через несколько часов после использования.
Чтобы ответить на вопрос: «Учитывая мою проблему и контекст, какую пользу мне принесет асинхронная работа webAPI?» учитывая, что это «довольно долгая операция», я думаю, много секунд, а не мс, этот подход освобождает потоки IIS. Очевидно, вам также необходимо запустить службу Windows, которая сама потребляет ресурсы, но этот подход может предотвратить поток медленных запросов от кражи потоков из других частей системы.
источник