Task.ContinueWith не очень популярен в асинхронном коде?

Мы хотим выполнить вызов 10 задач параллельно и обрабатывать каждый из 10 результатов параллельно.

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

фрагмент

private async Task<List<bool>> TransformJobsAsync(
            List<T> jobs)
        {
            var result = new List<bool>() { true };
            var tasks = new List<Task<bool>>(jobs.Count);

            try
            {
                foreach (var j in jobs)
                {
tasks .Add(InvokeSomeAsync(j).ContinueWith(x => HandleResultAsync(x, j)).Unwrap());
                }

                await Task.WhenAll(tasks);
                return tasks.Select(x => x.Result).ToList();
            }
            catch (Exception ex)
            {
                result = new List<bool>() { false };
            }
            return result;
        }



Task<(T response, T job)> InvokeSomeAsync        (T  job)
        {
            var cts = new CancellationTokenSource();

            try
            {
                cts.CancelAfter(30000);


var response = await SomeThirdPartyApi(request, cts.Token);

                if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
                {

                }


                return (response, job);
            }
            catch (OperationCanceledException opexException)
            {
                contextMessage = Messages.TranformationExecutionTimedOut;
            }
            catch (Exception ex)
            {
                contextMessage = Messages.UnHandledException;
            }
            finally
            {
                cts = null; //why? suggested pattern? review.
            }



            return await Task.FromException<(response, T Job)>(
                throw new Exception());
        }


    async Task<bool> HandleResultAsync(Task<(T response, T job)> task,                                                         T job)
            {

                try
                {
                    if (task.Status == TaskStatus.RanToCompletion)
                    {
                        if (task.Result.Status)
                        {
                            response = await CallMoreAsync(task.Result.reponse,
                                job, currentServiceState);
                        }
                        else
                        {
                            //log returned response = false
                        }
                    }
                    else
                    {
                        //log task failed
                    }
                }
                catch (Exception ex)
                {
                    response = false;
                }
                finally
                {
                    await DoCleanUpAsync();
                }
                return response;
            }

Я хотел знать, есть ли лучший шаблон, и continuewith не подходит для использования!

Иногда мы получаем эту ошибку, System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException (ошибка SocketError)

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
0
82
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы не должны использовать ContinueWith. ContinueWith — низкоуровневый и опасный способ сделать то же самое, что и await. Вместо этого современный код должен использовать await.

Чтобы объединить две асинхронные операции (например, InvokeSomeAsync и HandleResultAsync), введите метод async:

async Task<bool> InvokeAndHandleResultAsync<T>(T job)
{
  var task = InvokeSomeAsync(job);
  return await HandleResultAsync(task, job);
}

Затем это можно использовать в вашем foreach:

foreach (var j in jobs)
{
  tasks.Add(InvokeAndHandleResultAsync(j));
}

Другие примечания:

  • CancellationTokenSource следует утилизировать.
  • await Task.From* обычно желтый флаг.
  • Использование Task.Status — это красный флаг.
  • Используйте исключения для исключительных ситуаций, а не получайте bool результат с contextMessage состоянием где-то еще.

Я бы написал что-то вроде:

async Task InvokeAndHandleResultAsync<T>(T job)
{
  using (var cts = new CancellationTokenSource(30000))
  {
    try
    {
      var response = await SomeThirdPartyApi(request, cts.Token);
      if (!response.Status)
      {
        //log returned response = false
        return;
      }

      await CallMoreAsync(response, job, currentServiceState);
    }
    catch (Exception ex)
    {
      //log task failed
    }
    finally
    {
      await DoCleanUpAsync();
    }
  }
}

Кроме того, вместо создания списка задач вы можете упростить этот код:

private async Task TransformJobsAsync(List<T> jobs)
{
  return Task.WhenAll(jobs.Select(j => InvokeAndHandleResult(j)));
}

Большое спасибо, будет рефакторинг и отзывы.

Vijay.Gopalakrishna 22.05.2019 16:11

Здравствуйте, Стивен, не знаю, как избежать использования Task.Status! Спасибо

Vijay.Gopalakrishna 22.05.2019 16:25

ОК, рефакторинг для возврата ответа об отказе вместо возбуждения исключения!

Vijay.Gopalakrishna 22.05.2019 17:24
not sure how to avoid Using Task.Status — я рекомендую использовать await и разрешать распространение исключений.
Stephen Cleary 22.05.2019 18:15

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