Использование Async / Await с веб-API служб приложений Azure - PullRequest
0 голосов
/ 19 марта 2019

У меня есть .Net Web Api, размещенный как служба приложений Azure. (Я должен назвать это из ADF как веб-активность.)

Этот API имеет некоторый код, который выполняется долго, поэтому Я хочу сделать этот Async .

Вот как я тестирую:

[Route("apiA/[controller]")]
    [ApiController]
    public class AsynccallController : ControllerBase
    {

        [HttpPost]
        public async Task<String> PostA()
        {
            var strTask = await Longfunction();
            return strTask;
        }

        private Task<string> Longfunction()
        {
            Thread.Sleep(TimeSpan.FromSeconds(300));
            return Task.FromResult("value1");
        }

    }

И тестирование от почтальона: enter image description here

Согласно этой документации , ключевое слово await должно возвращать элемент управления функции вызывающей стороны (в данном случае почтальону) перед выполнением сна. Но я не вижу, чтобы это произошло. Эти 300 секунд все еще ждут отправки ответа почтальону, который похож на синхронизирующий вызов. почему?

И, во-вторых, если он отправляет управление обратно в ожидании, то когда и как оператор return отправляет значение обратно?

Спасибо.

Ответы [ 2 ]

1 голос
/ 21 марта 2019

В этом API есть некоторый код, который выполняется долгое время, поэтому я хочу сделать этот асинхронный.

Этот ответ рекомендует "асинхронный шаблон".В частности, это шаблон асинхронного обмена сообщениями .Этот шаблон не имеет ничего общего с ключевыми словами async и await.В шаблоне асинхронного обмена сообщениями используется термин «асинхронный» с очень широким определением;Ключевое слово async - это одна очень специфическая реализация асинхронности, которая здесь не применяется.

Чтобы на самом деле решить вашу проблему, вы должны заставить свой метод действия сгенерировать идентификатор запроса, добавить сообщение «запрос» в надежныйочередь (например, очередь Azure) и верните идентификатор запроса клиенту.Далее вам понадобится независимый фоновый работник;поскольку ваше веб-приложение является службой приложений Azure, вы можете найти веб-задания Azure хорошим выбором для фоновых работников, хотя вам следует учитывать и функции Azure.Наконец, вам понадобится способ связи рабочего с вашим интерфейсом, чтобы он знал, когда работа будет завершена;Здесь существует множество возможных подходов, от SignalR до некоторой общей «рабочей базы данных», которую веб-интерфейс может опрашивать через ваш API-интерфейс службы приложений.

И, во-вторых, если он отправляет управление обратно в 'ждите ', тогда когда и как оператор return отправляет значение обратно?

Вы правы;HTTP-ответ не может быть отправлен обратно на await, иначе невозможно будет отправить фактическое значение результата в качестве ответа.

Согласно этой документации,Ключевое слово await должно возвращать элемент управления функции вызывающей стороны (в данном случае почтальону)

Именно в этом и заключается недоразумение.Почтальон не вызвал вашу функцию;ASP.NET сделал.await правильно уступает ASP.NET, который возвращает поток запроса в пул потоков.ASP.NET не завершает запрос, пока не завершится метод действия.

1 голос
/ 19 марта 2019
  1. Вы почти никогда не хотите использовать Thread.Sleep() - Task.Delay() использует Timer под колпаком и является асинхронным (что позволяет потоку выполнять другую работу), в то время как Thread.Sleep блокирует!
  2. Вы можете - гипотетически - "выстрелить и забыть", пропустив await перед вызовом Longfunction() или используя Task.Run(() => Longfunction()) - имейте в виду, что это не очень разумно, например. Ваша задача не защищена от повторного использования пула приложений.
  3. Если вы хотите правильно разгрузить длительные операции, я настоятельно рекомендую вам заглянуть в Hangfire .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...