Запустите параллельное задание и верните первое выполненное задание, а другое запустите в фоновом режиме, чтобы сохранить результаты. - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть WebApi. NET CORE 3.1, в котором я пытаюсь получить результаты от службы (другой третьей стороны). Я создал несколько запросов в своем API для одной и той же службы, но некоторые параметры каждого запроса различны, результаты, возвращаемые службой, будут разными для каждого запроса, но структура результата будет одинаковой.

Поскольку все запросы независимо друг от друга, я хочу запустить все это параллельно. И я хочу вернуть первый результат, как только получен от сервиса от моего API, но я также хочу запускать все другие запросы в фоновом режиме и сохранять там результаты в REDIS.

Я попытался создать пример кода чтобы проверить, если возможно:

        [HttpPost]
        [Route("Test")]
        public async Task<SearchResponse> Test(SearchRequest req)
        {
            List<Task<SearchResponse>> TaskList = new List<Task<SearchResponse>>();
            for (int i = 0; i < 10; i++)
            {
                SearchRequest copyReq = Util.Copy(req); // my util function to copy the request
                copyReq.ChangedParameter = i; // This is an example, many param can changed
                TaskList.Add(Task.Run(() => DoSomething(copyReq)));
            }

            var finishedTask = await Task.WhenAny(TaskList);

          return  await finishedTask;
        }

        private async Task<SearchResponse> DoSomething(SearchRequest req)
        {
            // Here calling the third party service
             SearchResponse resp = await service.GetResultAsync(req);


           // Saving the result in REDIS
            RedisManager.Save("KEY",resp);

             return resp;            
        }

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

РЕДАКТИРОВАТЬ

Сценарий использования

Я создал веб-приложение, которое будет извлекать результаты из моего webapi и отображать результаты. WebApp ищет список продуктов (может быть что угодно), отправляя запрос в мой API. Теперь мой API создает различные запросы, так как source (скажем, Site1 и Site2) для результатов могут отличаться.

Теперь третье лицо обрабатывает все запросы к разным источникам (Site1 и Site2) и преобразует полученные результаты в мою структуру результатов. Я просто должен указать параметр, с какого сайта я хочу получить результаты, а затем вызвать службу на моем конце.

Теперь я хочу отправить результаты в мое WebApp, как только появится любой источник (site1 или site2). дает мне результат, и в фоновом режиме я хочу сохранить результат из другого источника в Redis. Так что я могу получить это тоже из моего веб-приложения по другому запросу.

1 Ответ

1 голос
/ 27 апреля 2020

Код выглядит довольно хорошо; есть только одна настройка, которую я бы порекомендовал: не используйте Task.Run. Task.Run вызывает переключение потоков, которое здесь совершенно не нужно.

[HttpPost]
[Route("Test")]
public async Task<SearchResponse> Test(SearchRequest req)
{
  var TaskList = new List<Task<SearchResponse>>();
  for (int i = 0; i < 10; i++)
  {
    SearchRequest copyReq = Util.Copy(req); // my util function to copy the request
    copyReq.ChangedParameter = i; // This is an example, many param can changed
    TaskList.Add(DoSomething(copyReq));
  }

  return await await Task.WhenAny(TaskList);
}

private async Task<SearchResponse> DoSomething(SearchRequest req)
{
  // Here calling the third party service
  SearchResponse resp = await service.GetResultAsync(req);

  // Saving the result in REDIS
  RedisManager.Save("KEY",resp);

  return resp;            
}

Обратите внимание, что здесь используется функция «забей и забудь». В общем смысле, запускать и забывать опасен, так как это означает, что вам все равно, если код завершится неудачей или даже завершится. В этом случае, поскольку код обновляет только кэш, допускается запуск и забытие.

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