Использование Parallel.ForEachAsync

#c# #asynchronous #parallel-processing #parallel.foreachasync

#c# #асинхронный #параллельная обработка #parallel.foreachasync

Вопрос:

Я пытаюсь запустить Parallel.ForEachAsync() , но я получаю эти две ошибки:

Ошибка 1:
Аргумент 2: не удается преобразовать из системы.Многопоточность.Задачи.Параллельные варианты для системы.Многопоточность.
Ошибка CancellationToken 2:
функция делегирования<WC, CancellationToken, ValueTask> не принимает 1 аргумент

И это мой код:

 public async Task<List<DisplayDto>> GetData()
{
    var options = new ParallelOptions()
    {
        MaxDegreeOfParallelism = 20;
    };

    await Parallel.ForEachAsync(result, options, async OrderNumber => {
        //Do Stuff here. 
    });
}
 

Что нужно изменить, чтобы это работало так, как я хочу?

Комментарии:

1. Что это за тип result ?

Ответ №1:

Parallel.ForEachAsync ожидает Func<TSource,CancellationToken,ValueTask> , т.е. принимает 2 параметра (первый является элементом коллекции, а второй — CancellationToken ), а не один. Использование может выглядеть так:

 public async Task<List<DisplayDto>> GetData()
{
    var options = new ParallelOptions()
    {
        MaxDegreeOfParallelism = 20
    };

    await Parallel.ForEachAsync(result, options, async (OrderNumber, ct) => {
        // do not forget to use CancellationToken (ct) where appropriate 
        // Do Stuff here. 
    });
 }
 

Пример.

Комментарии:

1. и ct в async (OrderNumber, ct) этом CancellationToken случае?

2. @DoctorFord да.

3. Существует проблема с вашим кодом — вы не можете фактически использовать (ct), поскольку вы никогда не предоставляли его. Вам нужно передать токен отмены следующим Parallel.ForEachAsync(result, myCancelToken, async (OrderNumber, ct) => { }); образом Или, похоже, вы также можете назначить свой токен CancellationToken свойству ParallelOptions

4. @snow_FFFFFF «на самом деле вы не можете использовать (ct), поскольку вы его никогда не предоставляли». — это зависит от того, что вы подразумеваете / понимаете под «использованием». Что я имел в виду под использованием, так это анализ состояния отмены — в этом случае вы действительно можете вызвать Parallel.ForEachAsync will, если программист этого не сделал (бывают ситуации, когда ForEachAsync реализация отменяет ее, о которой я знаю — одна из задач приведет к исключению). «Вам нужно передать токен отмены» , как я объяснил — нет, это не требуется.

5. Спасибо за образец — моей первой реакцией было то, что на самом деле токен не использовался, но я вижу, что исключение действительно указывает на отмену. Это, безусловно, подтверждает, что документация MS мне непонятна, но, надеюсь, эта строка комментариев будет полезна кому-то еще 🙂