Длинный вызов API - Async вызывает ответ?

Я вызываю внешний 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 await, но я думаю, что мой сценарий выпадает из прочтения, которое я сделал до сих пор?

Вопросов:

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

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

Добро пожаловать в ebay api;) медленно как

TheGeneral 30.10.2018 05:00

Проблема не столько в том, чтобы делать что-то асинхронно (это не ускорит), а в том, чтобы делать вызовы параллельно. Как говорит TheGeneral, у ebay нет поддержки асинхронности. Таким образом, вы можете развернуть x потоков, каждый из которых выполняет синхронный вызов для каждой страницы. Просто не создавайте 20 потоков. Spawn = количество ЦП. Или вы можете взглянуть на TPL DataFlow. Лучшее долгосрочное вложение.

MickyD 30.10.2018 05:42

@MickyD Да, извините, моя терминология, вероятно, неверна. Я ищу параллельные звонки. Я исследую ответ от генерала

Glen Hong 30.10.2018 05:49

Не стоит беспокоиться. Я согласен с ответом TheGeneral :)

MickyD 30.10.2018 05:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
446
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

I think I can set it up to fire off the multiple calls asynchronously but I'm not sure how to check when all tasks have been completed i.e. ready to commit to db.

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

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

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

Пример

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, хотя на самом деле не имеет значения, сколько вы его дадите, Планировщик заданий не будет агрессивно давать вам потоки, может быть, 10 или около того изначально и медленно расти.

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


I've read somewhere that I want to avoid combining the API call and the db write to avoid locking in SQL server - Is this correct?

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

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

Для (Int32, Int32, ParallelOptions, Action)

Executes a for (For in Visual Basic) loop in which iterations may run in parallel and loop options can be configured.

ParallelOptions Класс

Stores options that configure the operation of methods on the Parallel class.

MaxDegreeOfParallelism

Gets or sets the maximum number of concurrent tasks enabled by this ParallelOptions instance.

Класс ConcurrentBag

Represents a thread-safe, unordered collection of objects.

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

Glen Hong 30.10.2018 05:51

@GlenHong с parallel.For ожидает завершения всех потоков, следовательно, вам понадобится только одна однопоточная операция db. Однако есть много причин для тупика БД, и это полностью зависит от вашей базы данных, схемы и вашего sql.

TheGeneral 30.10.2018 05:54

спасибо работает отлично. Любые подсказки о том, как поступить, если в одном из этих потоков возникла ошибка, т.е. тайм-аут?

Glen Hong 30.10.2018 06:47

@GlenHong, вы могли бы добавить механизм повтора в блок кода для страницы. или вы можете поймать и добавить еще один concurrentbag, чтобы потом рассказать вам, какая страница вышла из строя и почему. может быть смесь обоих

TheGeneral 30.10.2018 06:49

Спасибо ... Я нашел ссылку docs.microsoft.com/en-us/dotnet/standard/parallel-programmin‌ g /…, которая помогает. Я думаю, что на самом деле единственное, что может здесь произойти, - это тайм-аут или потеря соединения. А пока я просто поймаю все и сообщу пользователю, чтобы он попробовал еще раз. Далее я буду реализовывать, когда вы предлагаете повторить попытку ...

Glen Hong 30.10.2018 06:56

@GlenHong звучит как план и хорошая ссылка

TheGeneral 30.10.2018 06:59

Я мог бы просто добавить, что мне пришлось определить GetOrdersCall в Parallel, иначе я думаю, что это сбивало с толку, и количество одновременных пакетов не было всеми заказами. Определение переменных внутри цикла решило эту проблему.

Glen Hong 31.10.2018 06:21

Однако быстрый вопрос - у меня есть 3 магазина, и я думал запустить вложенный Parallel.for (по одному для каждого магазина), а затем вложенный (по одному для каждой страницы результатов) - возможно ли это? Я задам новый вопрос, если хотите?

Glen Hong 31.10.2018 06:22

@GlenHong: да, вы можете безопасно выполнять вложение, однако в любом случае система выдаст вам только определенное количество потоков, может быть, 10 для запуска. Если вы действительно хотите более высокую пропускную способность, вы можете развернуть класс Thread и управлять ими.

TheGeneral 31.10.2018 06:24

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

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

Если я не ошибаюсь, это API ebay, и здесь нет асинхронных методов. также это не решает проблему асинхронного получения заказов для экономии времени

TheGeneral 30.10.2018 05:28

Спасибо за информацию, над ebay api еще не работал. Но проведем исследование по этому поводу.

Rashedul.Rubel 30.10.2018 06:53

Другие вопросы по теме