Исключение из PLinq AsParallel async приводит к сбою приложения

Мой вопрос заключается в захвате исключений в методе ForAll под Plinq

Я пытался выполнить задачи с заданием максимального количества потоков. Использование перечислимого .AsParallel () .WithDegreeOfParallelism (100) .ForAll (async item => ждет AsyncTask ())

Он работает, но если AsyncTask выдает исключение, приложение отключается.

Я сделал следующее испытание:

try
{
   IEnumerable<string> enumerable = new List<string> { "st", "st" };
   enumerable.AsParallel()
   .ForAll(async f =>
   {
      try
      {
          throw new Exception(); // Or await AsyncTask that throws this
      }
      catch (Exception e)
      {
          e.ToString(); **// This Exception is captured**
          throw e;
      }
   });
}
catch (Exception e) **// THIS IS NOT CAPTURED AND THE APP CRASHES**
{
   e.ToString();
}
  1. И я хотел бы понять причины этого
  2. И другие варианты реализации

c#,asp.net,.net,asp.net-core,

0

Ответов: 1


1

enumerable.AsParallel (). ForAll () выполняет задание для каждого элемента вашего перечисления параллельно. Поскольку ваше задание является асинхронным, ForAll () не ожидает завершения всех действий. В этом случае исполняемый код покидает блок try..catch, прежде чем ваш метод AsyncTask () выдает исключение. Это может привести к необработанному исключению, которое приведет к сбою вашего приложения.

Не имеет значения, что вы пытаетесь подождать AsyncTask (), потому что ForAll () получает простое действие и не ждет результата вашей AsyncTask ().

Возможным решением может стать запуск AsyncTasks для каждого элемента без AsParallel (). ForEach () и ожидание результатов позже в вашей try..catch.

При хранении

Task or Task<T>

в результате вы можете проверить, выбрала ли какая-либо задача исключение, используя свойство task.Exception.

Вы можете сделать что-то вроде этого:

    private async Task DoSomethingAsync()
    {
        try
        {
            IEnumerable<string> enumerable = new List<string> { "st", "st" };

            // start all tasks and store them in an array
            var tasks = enumerable.Select(TaskAsync).ToArray();

            // do something more without waiting until all tasks above completed
            // ...


            // await all tasks
            var completionTask = Task.WhenAll(tasks);
            await completionTask;

            // handle task exception if any exists
            if (completionTask.Status == TaskStatus.Faulted)
            {
                foreach (var task in tasks)
                {
                    if (task.Exception != null)
                    {
                        // throw an exception or handle the exception, e.g. log the exceptions to file / database
                    }
                }
            }
        }
        catch (Exception e)
        {
            // handle your exception, e.g. write a log to file / database
        }
    }

    private Task TaskAsync(string item)
    {
        // Task.Delay() is just a placeholder
        // do some async stuff here, e.g. access web services or a database
        return Task.Delay(10000);
    }
C #, asp.net, .net asp.net-жильный,
Похожие вопросы