Длинный вызов API - Async вызывает ответ? - PullRequest
0 голосов
/ 30 октября 2018

Я вызываю внешний API, который работает медленно. В настоящее время, если я не вызывал API, чтобы получить какие-то заказы на некоторое время, звонок можно разбить на страницы (разбиение на страницы).

Таким образом, для получения заказов может использоваться несколько вызовов, а не один вызов. Иногда каждый звонок может занимать около 10 секунд на звонок, так что это может быть всего около минуты, что слишком долго.

        GetOrdersCall getOrders = new GetOrdersCall();
        getOrders.DetailLevelList.Add(DetailLevelCodeType.ReturnSummary);
        getOrders.CreateTimeFrom = lastOrderDate;
        getOrders.CreateTimeTo = DateTime.Now;

        PaginationType paging = new PaginationType();
        paging.EntriesPerPage = 20;
        paging.PageNumber = 1;

        getOrders.Pagination = paging;

        getOrders.Execute();

        var response = getOrders.ApiResponse;
        OrderTypeCollection orders = new OrderTypeCollection();

        while (response != null && response.OrderArray.Count > 0)
        {
            eBayConverter.ConvertOrders(response.OrderArray, 1);

            if (response.HasMoreOrders)
            {
                getOrders.Pagination.PageNumber++;
                getOrders.Execute();

                response = getOrders.ApiResponse;
                orders.AddRange(response.OrderArray);
            }
        }

Это краткое изложение моего кода выше ... getOrders.Execute () - это время, когда API запускается.

После 1-го «getOrders.Execute ()» появляется результат разбиения на страницы, который сообщает мне, сколько страниц данных есть. Я думаю, что я должен иметь возможность начать асинхронный вызов для каждой страницы и заполнить коллекцию OrderTypeCollection. Когда все вызовы будут сделаны и коллекция будет полностью загружена, я внесу в базу данных.

Я никогда раньше не делал асинхронные вызовы через c #, и я могу как следует ожидать Async, но я думаю, что мой сценарий выпадает из чтения, которое я сделал до сих пор?

Вопросы:

  1. Я думаю, что могу настроить его на асинхронный запуск нескольких вызовов, но я не уверен, как проверить, когда все задачи были выполнены, т.е. готовы ли зафиксировать в db.
  2. Я где-то читал, что хочу избежать объединения вызова API и записи в БД, чтобы избежать блокировки на SQL-сервере - это правильно?

Если кто-то может направить меня в правильном направлении - это будет с благодарностью.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Да ConcurrentBag<T> Класс может быть использован для сервера с целью одного из ваших вопросов, который был: «Я думаю, я могу настроить его на асинхронный запуск нескольких вызовов, но я не уверен, как проверить, когда все задачи были завершены, т.е. готовы к передаче в БД. "

Этот универсальный класс можно использовать для запуска каждой задачи и ожидания завершения всех задач для дальнейшей обработки. Это потокобезопасно и полезно для параллельной обработки.

0 голосов
/ 30 октября 2018

Я думаю, что могу настроить его на асинхронный запуск нескольких вызовов но я не уверен, как проверить, когда все задачи были выполнены, т.е. готов совершить в БД.

Да, вы можете разбить это

Проблема заключается в том, что ebay не имеет async Task Execute метода, поэтому у вас остаются блокированные вызовы с нитями и без оптимизированного для ввода-вывода асинхронного шаблона ожидания. Если бы это было так, вы могли бы воспользоваться TPL Dataflow конвейером, который async осведомлен (и интересно для всей семьи играть), вы могли бы в любом случае, хотя я предлагаю ванильный TPL решение ...

Однако, еще не все потеряно, просто вернитесь к Parallel.For и ConcurrentBag<OrderType>

* ** 1023 тысяча двадцать-дв * Пример
var concurrentBag = new ConcurrentBag<OrderType>();


// make first call
// add results to concurrentBag
// pass the pageCount to the for
int pagesize = ...;

Parallel.For(1, pagesize,
   page =>
      {
         // Set up
         // add page
         // make Call 

         foreach(var order in getOrders.ApiResponse)
            concurrentBag.Add(order);
      });

// all orders have been downloaded
// save to db

Примечание : есть MaxDegreeOfParallelism, который вы настраиваете, возможно, установите его на 50, хотя на самом деле не имеет значения, сколько вы его дадите, Task Scheduler не собирается агрессивно давать вам темы, может быть, 10 или около того вначале и расти медленно.

Другой способ сделать это - создать свой собственный планировщик задач или просто раскрутить свои собственные потоки со старомодным Thread Class


Я где-то читал, что хочу избежать объединения вызова API и запись в БД, чтобы избежать блокировки на сервере SQL - это правильно?

  • Если вы имеете в виду блокировку, как при медленной вставке БД, используйте Sql Bulk Insert и обновите инструменты.
  • Если вы имеете в виду блокировку, как в сообщении об ошибке взаимоблокировки БД, то это совсем другое дело и заслуживает отдельного вопроса

Дополнительные ресурсы

Для (Int32, Int32, ParallelOptions, Действие)

Выполняет цикл for (For в Visual Basic), в котором могут выполняться итерации. параллельно и параметры петли могут быть настроены.

Класс ParallelOptions

Хранит параметры, которые настраивают работу методов на параллели класс.

MaxDegreeOfParallelism

Получает или задает максимальное количество одновременных задач, разрешенных этим Экземпляр ParallelOptions.

Класс ConcurrentBag

Представляет потокобезопасный неупорядоченный набор объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...